关于本题折半搜索做法的一些疑问
查看原帖
关于本题折半搜索做法的一些疑问
333785
xqh07楼主2024/8/14 00:03

鄙人不才,使用折半搜索,思路是将棋盘状态压缩成二进制并单独记录空位。

我原本怕复杂度太大,只敢从目标状态预处理出 88 步以内的状态,然后从询问状态走 77 步以内检验能否对接。喜提 WA 5050 分。后来把目标状态的 88 调成 1111, 就 AC 了?请问大佬们为什么?

#include <bits/stdc++.h>
using namespace std;
int T, n, m, ans;
char s[10][10];
int sx[] = {-2, -2, -1, -1, 1, 1, 2, 2};
int sy[] = {-1, 1, -2, 2, 2, -2, -1, 1};
map<int, int> mp[15][15];
map<int, bool> pp[15][15];
int get(int x, int y)
{
	return x * 5 + y;
}
void dfs(int t, int x, int y, int z)
{
	if(t == 12 || (mp[x][y][z] && mp[x][y][z] <= t)) return ; // 在这里从9改成了12
	mp[x][y][z] = t;
	int lp = get(x, y);
	for(int i = 0; i < 8; i++)
	{
		int X = x + sx[i], Y = y + sy[i], pos = get(X, Y), Z = z;
		if(X < 0 || X > 4 || Y < 0 || Y > 4) continue;
		if((Z >> pos) & 1) 
		{
			Z = Z &~(1 << pos), Z |= (1 << lp);
			dfs(t + 1, X, Y, Z);
		}
		else
		{
			dfs(t + 1, X, Y, Z);
		}
	}
}
void ddd(int t, int x, int y, int z)
{
	if(t == 7) return ;
	if(mp[x][y][z]) 
		ans = min(ans, t + mp[x][y][z] - 1);
	int lp = get(x, y);
	for(int i = 0; i < 8; i++)
	{
		int X = x + sx[i], Y = y + sy[i], pos = get(X, Y), Z = z;
		if(X < 0 || X > 4 || Y < 0 || Y > 4) continue;
		if((Z >> pos) & 1) 
		{
			Z = Z &~(1 << pos), Z |= (1 << lp);
			ddd(t + 1, X, Y, Z);
		}
		else
		{
			ddd(t + 1, X, Y, Z);
		}
	}
}
signed main()
{
	dfs(1, 2, 2, 549855);
	scanf("%d", &T);
	while(T--)
	{
		for(int i = 0; i <= 4; i++)
			for(int j = 0; j <= 4; j++)
				pp[i][j].clear();
		ans = 1e9;
		for(int i = 0; i < 5; i++) scanf("%s", s[i]);
		int x = 0, y = 0, z = 0;
		for(int i = 0; i < 5; i++)
		{
			for(int j = 0; j < 5; j++)
			{
				if(s[i][j] == '*') x = i, y = j;
				if(s[i][j] == '1') z += (1 << get(i, j));
			}
		}
		ddd(0, x, y, z);
		if(ans <= 15) printf("%d\n", ans);
		else printf("-1\n");
	}
	return 0;
}

2024/8/14 00:03
加载中...