题目传送门:https://www.luogu.org/problemnew/show/P2324
题意:
有一副5*5棋盘,0表示白色骑士,1表示黑色骑士,求多久时候可以变为目标状态。
目标状态如下:
思路:
一开始用双向广搜,不仅TLE(可能是不能用双向广搜),还WA(还是我太弱了)。
于是怒翻一波题解,发现是迭代加深。
不会,仔细读题解(太弱……)。
详见代码。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int map[5][5]={{ 1, 1, 1, 1, 1},
{ 0, 1, 1, 1, 1},
{ 0, 0,-1, 1, 1},
{ 0, 0, 0, 0, 1},
{ 0, 0, 0, 0, 0}};//初始矩阵
const int fx[8]={1, 1,-1,-1,2, 2,-2,-2};
const int fy[8]={2,-2, 2,-2,1,-1, 1,-1};
struct node{int x,y,p;};
int n,m,ans;
int a[10][10];
node compare()
{
int tot=0;
node u;
u.p=0;
for(int i=1;i<=5;i++)
for(int j=1;j<=5;j++)
{
if(a[i][j]==-1) u.x=i,u.y=j;
u.p+=a[i][j]!=map[i-1][j-1];
}
return u;
}
bool dfs(int now)//now表示当前走了now遍
{
node k=compare();//看一看离结果还有多少个不相同,同时找出空位
if(!k.p) return true;//如果已经相同,已经找到答案
if(now+k.p-1>ans) return false;//如果现在步数+相差个数-1已经大于当前必须答案,一定不为结果.-1因为你每走1步,都会产生两个点发生改变;走两步,产生三个点发生改变,以此类推
for(int i=0;i<=7;i++)
{
int t1=k.x+fx[i],t2=k.y+fy[i];//去找下一次的空位
if(t1<1||t1>5||t2<1||t2>5) continue;
swap(a[k.x][k.y],a[t1][t2]);
if(dfs(now+1)) return true;
swap(a[k.x][k.y],a[t1][t2]);
}
return false;
}
int main()
{
int T;
char s[10];
scanf("%d",&T);
while(T--)
{
for(int i=1;i<=5;i++)
{
scanf("%s",s+1);
for(int j=1;j<=5;j++)
a[i][j]=s[j]=='*'?-1:s[j]-48;
}
for(ans=1;ans<=15;ans++)//枚举答案
if(dfs(0)) break;
printf("%d\n",ans<=15?ans:-1);
}
}