开始怼网络流24题所以发的比较晚,学习一下A*搜索,A*其实就是加入评估函数对有限步数或能估价有效的剪枝,对于A*一般只有dfs(bfs被成为最愚蠢的A*)。
这题的估价函数:当前棋盘与目标棋盘不同的位置数量-1(评估函数是当前状态到目标状态的距离),所以就有:
当前不相同的骑士个数 + 当前步数 <= 期望最大步数
若不满足就剪枝
代码:
#include<iostream>
#include<stdio.h>
using namespace std;
char graph[7][7]={
"000000",
"011111",
"001111",
"000*11",
"000001",
"000000"};
char c[7][7];
int now,flag;
inline int ftry()
{
int ans=0;
for(int i=1;i<=5;i++)
for(int j=1;j<=5;j++)
ans+=(c[i][j]!=graph[i][j]);
return ans-1;
}
inline void dfs(int depth,int x,int y)
{
int p=ftry();
if(p==-1)
{
flag=1;
return ;
}
if(p+depth>now)return ;
if(x+2<=5&&y+1<=5&&x+2>=1&&y+1>=1){swap(c[x+2][y+1],c[x][y]);dfs(depth+1,x+2,y+1);swap(c[x+2][y+1],c[x][y]);if(flag)return ;}
if(x+2<=5&&y-1>=1&&x+2>=1&&y-1<=5){swap(c[x+2][y-1],c[x][y]);dfs(depth+1,x+2,y-1);swap(c[x+2][y-1],c[x][y]);if(flag)return ;}
if(x-2>=1&&y+1<=5&&x-2<=5&&y+1>=1){swap(c[x-2][y+1],c[x][y]);dfs(depth+1,x-2,y+1);swap(c[x-2][y+1],c[x][y]);if(flag)return ;}
if(x-2>=1&&y-1<=5&&x-2<=5&&y-1>=1){swap(c[x-2][y-1],c[x][y]);dfs(depth+1,x-2,y-1);swap(c[x-2][y-1],c[x][y]);if(flag)return ;}
if(x+1<=5&&y+2<=5&&x+1>=1&&y+2>=1){swap(c[x+1][y+2],c[x][y]);dfs(depth+1,x+1,y+2);swap(c[x+1][y+2],c[x][y]);if(flag)return ;}
if(x+1<=5&&y-2>=1&&x+1>=1&&y-2<=5){swap(c[x+1][y-2],c[x][y]);dfs(depth+1,x+1,y-2);swap(c[x+1][y-2],c[x][y]);if(flag)return ;}
if(x-1>=1&&y+2<=5&&x-1<=5&&y+2>=1){swap(c[x-1][y+2],c[x][y]);dfs(depth+1,x-1,y+2);swap(c[x-1][y+2],c[x][y]);if(flag)return ;}
if(x-1>=1&&y-2>=1&&x-1<=5&&y-2<=5){swap(c[x-1][y-2],c[x][y]);dfs(depth+1,x-1,y-2);swap(c[x-1][y-2],c[x][y]);if(flag)return ;}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int x,y;
flag=0;
for(int i=1;i<=5;i++)
{
scanf("\n");
for(int j=1;j<=5;j++)
{
scanf("%c",&c[i][j]);
if(c[i][j]=='*')
x=i,y=j;
}
}
for(now=0;now<=15;now++)
{
dfs(0,x,y);
if(flag)
break;
}
if(now==16)
now=-1;
printf("%d\n",now);
}
return 0;
}