1085: [SCOI2005]骑士精神
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1757 Solved: 961
[Submit][Status][Discuss]
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
【题解】
A*寻路法。
设计一个估价函数h=s+v,如果满足h<k就往下搜,否则不搜,这样就能过了。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cmath> 5 #include<ctime> 6 #include<cstring> 7 #include<algorithm> 8 using namespace std; 9 const int ans[5][5]={{1,1,1,1,1},{0,1,1,1,1},{0,0,2,1,1},{0,0,0,0,1},{0,0,0,0,0}}; 10 const int dx[8]={1,1,-1,-1,2,2,-2,-2}; 11 const int dy[8]={2,-2,2,-2,1,-1,1,-1}; 12 int T,x,y,flag,k,a[6][6]; 13 char map[6][6]; 14 inline int read() 15 { 16 int x=0,f=1; char ch=getchar(); 17 while(!isdigit(ch)) {if(ch=='-') f=-1; ch=getchar();} 18 while(isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();} 19 return x*f; 20 } 21 int check() 22 { 23 for(int i=0;i<5;i++) 24 for(int j=0;j<5;j++) 25 if(a[i][j]!=ans[i][j]) return 0; 26 return 1; 27 } 28 int gujia(int s) 29 { 30 int v=0; 31 for(int i=0;i<5;i++) 32 for(int j=0;j<5;j++) 33 if(a[i][j]!=ans[i][j]) {v++; if(v+s>k) return 0;} 34 return 1; 35 } 36 void search(int s,int x,int y) 37 { 38 if(s==k) {if(check()) flag=1; return;} 39 if(flag) return; 40 for(int i=0;i<8;i++) 41 { 42 int xx=x+dx[i],yy=y+dy[i]; 43 if(xx>4||xx<0||yy>4||yy<0) continue; 44 swap(a[x][y],a[xx][yy]); 45 if(gujia(s)) search(s+1,xx,yy); 46 swap(a[x][y],a[xx][yy]); 47 } 48 } 49 int main() 50 { 51 //freopen("cin.in","r",stdin); 52 //freopen("cout.out","w",stdout); 53 T=read(); 54 while(T--) 55 { 56 for(int i=0;i<5;i++) 57 for(int j=0;j<5;j++) 58 { 59 cin>>map[i][j]; 60 if(map[i][j]=='*') {a[i][j]=2; x=i; y=j;} 61 else a[i][j]=map[i][j]-'0'; 62 } 63 for(k=1;k<=15;k++) {search(0,x,y); if(flag) {printf("%d\n",k); break;}} 64 if(!flag) printf("-1\n"); 65 flag=0; 66 } 67 return 0; 68 }