bzoj 1085[SCOI2005]骑士精神 - IDA*
1085: [SCOI2005]骑士精神
Time Limit: 10 Sec Memory Limit: 162 MBDescription
在一个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
一道练习 IDA* 的好题
套一层循环表示最大步数限制,估价函数为所有不在位置的节点个数 -1
因为估价步数是最小步数,所以如果当前的步数 + 估价步数 > lim , 就可以return
跑到飞快。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <cmath> 6 #define LL long long 7 8 using namespace std; 9 10 int T; 11 int lim = 0; 12 int flag = 0; 13 char map[10][10]; 14 char rt[10][10]; 15 char status[10][10]; 16 int move[10][2]; 17 18 void init() 19 { 20 move[1][0] = 1, move[1][1] = 2; 21 move[2][0] = -1, move[2][1] = 2; 22 move[3][0] = 1, move[3][1] = -2; 23 move[4][0] = -1, move[4][1] = -2; 24 move[5][0] = 2, move[5][1] = 1; 25 move[6][0] = -2, move[6][1] = 1; 26 move[7][0] = -2, move[7][1] = -1; 27 move[8][0] = 2, move[8][1] = -1; 28 } 29 30 inline LL read() 31 { 32 LL x = 0, w = 1; char ch = 0; 33 while(ch < '0' || ch > '9') { 34 if(ch == '-') { 35 w = -1; 36 } 37 ch = getchar(); 38 } 39 while(ch >= '0' && ch <= '9') { 40 x = x * 10 + ch - '0'; 41 ch = getchar(); 42 } 43 return x * w; 44 } 45 int judge() 46 { 47 int sum = 0; 48 for(int i = 1; i <= 5; i++) { 49 for(int j = 1; j <= 5; j++) { 50 if(status[i][j] != rt[i][j]) { 51 sum++; 52 } 53 } 54 } 55 return sum; 56 } 57 58 void DFS(int x, int y, int step) 59 { 60 if(flag) { 61 return; 62 } 63 int astar = judge(); 64 if(astar == 0) { 65 flag = 1; 66 return; 67 } 68 astar--; 69 if(step + astar > lim) { 70 return; 71 } 72 for(int i = 1; i <= 8; i++) { 73 int xx = x + move[i][0], yy = y + move[i][1]; 74 char last; 75 if(xx >= 1 && xx <= 5 && yy >= 1 && yy <= 5) { 76 last = status[xx][yy]; 77 status[xx][yy] = '*'; 78 status[x][y] = last; 79 DFS(xx, yy, step + 1); 80 status[xx][yy] = last; 81 status[x][y] = '*'; 82 } 83 } 84 } 85 86 int main() 87 { 88 init(); 89 for(int i = 1; i <= 5; i++) { 90 for(int j = 1; j <= 5; j++) { 91 rt[i][j] = '0'; 92 } 93 } 94 for(int i = 1; i <= 2; i++) { 95 for(int j = i; j <= 5; j++) { 96 rt[i][j] = '1'; 97 } 98 } 99 for(int i = 3; i <= 4; i++) { 100 for(int j = i + 1; j <= 5; j++) { 101 rt[i][j] = '1'; 102 } 103 } 104 rt[3][3] = '*'; 105 T = read(); 106 while(T--) { 107 flag = 0; 108 int x, y; 109 for(int i = 1; i <= 5; i++) { 110 scanf("%s", map[i] + 1); 111 for(int j = 1; j <= 5; j++) { 112 if(map[i][j] == '*') { 113 x = i, y = j; 114 } 115 } 116 } 117 for(lim = 0; lim <= 15; lim++) { 118 for(int i = 1; i <= 5; i++) { 119 for(int j = 1; j <= 5; j++) { 120 status[i][j] = map[i][j]; 121 } 122 } 123 DFS(x, y, 0); 124 if(flag) { 125 printf("%d\n", lim); 126 break; 127 } 128 } 129 if(!flag) { 130 printf("-1\n"); 131 } 132 } 133 } 134 135 136 /* 137 2 138 139 10110 140 141 01*11 142 143 10111 144 145 01001 146 147 00000 148 149 01011 150 151 110*1 152 153 01110 154 155 01010 156 157 00100 158 */