题目大意:给定一个棋盘,每个棋子都是骑士,问能否在15步之内移动为特定排布
此题采用IDA*
估价函数为:当前棋盘与目标棋盘不同的位置数量-1
易知一个棋盘最少需要这么多的步数才能达成目标棋盘
若当前步数+估价函数大于最大深度 则剪枝
优先搜索懒得写0.0 这样就能切掉就行
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int max_dpt,flag;
char map[6][6];
const int dx[]={1,1,-1,-1,2,2,-2,-2};
const int dy[]={2,-2,2,-2,1,-1,1,-1};
char tar[6][7]={
"000000",
"011111",
"001111",
"000*11",
"000001",
"000000"
};
inline char Get_Char()
{
char c;
do c=getchar(); while(c!='0'&&c!='1'&&c!='*');
return c;
}
int Evalute()
{
int i,j,re=0;
for(i=1;i<=5;i++)
for(j=1;j<=5;j++)
re+=map[i][j]!=tar[i][j];
return re-1;
}
void IDA8(int dpt,int x,int y)
{
int i,temp=Evalute();
if(temp==-1)
{
flag=1;
return;
}
if(temp+dpt>max_dpt)
return ;
for(i=0;i<8;i++)
{
int xx=x+dx[i];
int yy=y+dy[i];
if(xx<=0||yy<=0||xx>5||yy>5)
continue;
swap(map[x][y],map[xx][yy]);
IDA8(dpt+1,xx,yy);
swap(map[x][y],map[xx][yy]);
if(flag)
return ;
}
}
int main()
{
int T,i,j,x,y;
for(cin>>T;T;T--)
{
flag=0;
for(i=1;i<=5;i++)
for(j=1;j<=5;j++)
{
map[i][j]=Get_Char();
if(map[i][j]=='*')
x=i,y=j;
}
for(max_dpt=0;max_dpt<=15;max_dpt++)
{
IDA8(0,x,y);
if(flag)
break;
}
if(max_dpt==16)
max_dpt=-1;
cout<<max_dpt<<endl;
}
}