開始懟網絡流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;
}