1085: [SCOI2005]骑士精神
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 534 Solved: 280
[ Submit][ Status]
Description
在一个5×5的棋盘上有12个白色的骑士和12个黑色的骑士, 且有一个空位。在任何时候一个骑士都能按照骑士的走法(它可以走到和它横坐标相差为1,纵坐标相差为2或者横坐标相差为2,纵坐标相差为1的格子)移动到空位上。 给定一个初始的棋盘,怎样才能经过移动变成如下目标棋盘: 为了体现出骑士精神,他们必须以最少的步数完成任务。
Input
第一行有一个正整数T(T<=10),表示一共有N组数据。接下来有T个5×5的矩阵,0表示白色骑士,1表示黑色骑士,*表示空位。两组数据之间没有空行。
Output
对于每组数据都输出一行。如果能在15步以内(包括15步)到达目标状态,则输出步数,否则输出-1。
Sample Input
2
10110
01*11
10111
01001
00000
01011
110*1
01110
01010
00100
10110
01*11
10111
01001
00000
01011
110*1
01110
01010
00100
Sample Output
7
-1
-1
HINT
Source
这题数据较小,所以可以考虑搜索
这题的估价函数是比较好写的,对于每个格子,如果他与标准格子不同计数器+1,最后计数器-1一定《=实际代价,鉴于这题状态数多,而且只有15层,所以可以用IDA*
下面贴代码
/**************************************************************
Problem: 1085
User: SKYDEC
Language: C++
Result: Accepted
Time:1436 ms
Memory:804 kb
****************************************************************/
#include<stdio.h>
using namespace std;
struct chess{
long h[6][6];
}stdp;
long dx[10]={0,-1,-1,1,1,-2,-2,2,2};
long dy[10]={0,-2,2,-2,2,-1,1,-1,1};
long f(chess a)
{
long ans=0;
for(long i=1;i<=5;i++)
for(long j=1;j<=5;j++)
if(a.h[i][j]!=stdp.h[i][j])ans++;
ans--;
return ans;
}
bool flag=false;
void swap(long &a,long &b)
{
long t=a;a=b;b=t;
}
void A_star(long x,long y,chess now,long up,long step)
{
if(flag)return;
if(step>up)return;
if(f(now)==-1){flag=true;return;}
if(f(now)+step>up)return;
for(long i=1;i<=8;i++)
if(dx[i]+x>=1&&dx[i]+x<=5&&dy[i]+y>=1&&dy[i]+y<=5)
{
swap(now.h[x][y],now.h[x+dx[i]][y+dy[i]]);
//if(f(now)+step>up)return;
A_star(x+dx[i],y+dy[i],now,up,step+1);
swap(now.h[x][y],now.h[x+dx[i]][y+dy[i]]);
}
}
int main()
{
for(long i=1;i<=5;i++){stdp.h[1][i]=1;stdp.h[5][i]=0;}
stdp.h[2][1]=stdp.h[3][1]=stdp.h[3][2]=stdp.h[4][1]=stdp.h[4][2]=stdp.h[4][3]=stdp.h[4][4]=0;
stdp.h[2][2]=stdp.h[2][3]=stdp.h[2][4]=stdp.h[2][5]=stdp.h[3][4]=stdp.h[3][5]=stdp.h[4][5]=1;stdp.h[3][3]=2;
long test;scanf("%ld\n",&test);char goe;
for(long cao=1;cao<=test;cao++)
{
chess start;long sx,sy;
for(long i=1;i<=5;i++)
{
for(long j=1;j<=5;j++)
{
scanf("%c",&goe);
if(goe!='*')start.h[i][j]=goe-'0';else{start.h[i][j]=2;sx=i;sy=j;}
}
scanf("%c",&goe);
}
flag=false;
if(f(start)==-1)printf("0\n");
else
{
for(long i=1;i<=15;i++)
if(!flag)
{
A_star(sx,sy,start,i,0);
if(flag)printf("%ld\n",i);
}
if(!flag)printf("-1\n");
}
}
//for(;;);
return 0;
}