1085: [SCOI2005]骑士精神
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2895 Solved: 1707
[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
HINT
Source
A*搜索
估价函数:如果有n个点不在应在的位置上,至少移动n - 1步
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <algorithm> 6 #include <cmath> 7 #include <queue> 8 #include <vector> 9 #define min(a, b) ((a) < (b) ? (a) : (b)) 10 #define max(a, b) ((a) > (b) ? (a) : (b)) 11 #define abs(a) ((a) < 0 ? (-1 * (a)) : (a)) 12 inline void swap(int &a, int &b) 13 { 14 int tmp = a;a = b;b = tmp; 15 } 16 inline void read(int &x) 17 { 18 x = 0;char ch = getchar(), c = ch; 19 while(ch < ‘0‘ || ch > ‘9‘) c = ch, ch = getchar(); 20 while(ch <= ‘9‘ && ch >= ‘0‘) x = x * 10 + ch - ‘0‘, ch = getchar(); 21 if(c == ‘-‘)x = -x; 22 } 23 24 const int INF = 0x3f3f3f3f; 25 const int MAXN = 10 + 5; 26 const int dx[8] = {1,1,-1,-1,2,2,-2,-2}; 27 const int dy[8] = {2,-2,2,-2,1,-1,1,-1}; 28 const int ANS[6][6] = {{0,0,0,0,0,0}, 29 {0,1,1,1,1,1}, 30 {0,0,1,1,1,1}, 31 {0,0,0,2,1,1}, 32 {0,0,0,0,0,1}, 33 {0,0,0,0,0,0}}; 34 35 int t, ans, sx, sy, g[MAXN][MAXN]; 36 char s[MAXN]; 37 38 void dfs(int step, int res, int x, int y) 39 { 40 if(step > 16) return; 41 if(!res) 42 { 43 ans = min(ans, step - 1); 44 return; 45 } 46 for(register int i = 0;i < 8;++ i) 47 { 48 int nowx = x + dx[i], nowy = y + dy[i]; 49 if(nowx <= 0 || nowy <= 0 || nowx > 5 || nowy > 5) continue; 50 int tmp = res; 51 if(g[x][y] == ANS[x][y]) res += 1; 52 if(g[nowx][nowy] == ANS[x][y]) res -= 1; 53 if(g[x][y] == ANS[nowx][nowy]) res -= 1; 54 if(g[nowx][nowy] == ANS[nowx][nowy]) res += 1; 55 swap(g[x][y], g[nowx][nowy]); 56 if(res + step - 2 < min(ans, 15)) dfs(step + 1, res, nowx, nowy); 57 swap(g[x][y], g[nowx][nowy]); 58 res = tmp; 59 } 60 } 61 62 int main() 63 { 64 read(t); 65 for(;t;--t) 66 { 67 int res = 0; 68 for(register int i = 1;i <= 5;++ i) 69 { 70 scanf("%s", s + 1); 71 for(register int j = 1;j <= 5;++ j) 72 { 73 if(s[j] == ‘*‘) g[i][j] = 2, sx = i, sy = j; 74 else g[i][j] = s[j] - ‘0‘; 75 if(g[i][j] != ANS[i][j]) ++ res; 76 } 77 } 78 ans = INF; 79 dfs(1, res, sx, sy); 80 if(ans == INF) printf("-1\n"); 81 else printf("%d\n", ans); 82 } 83 return 0; 84 }