bzoj 1085[SCOI2005]骑士精神 - IDA*

1085: [SCOI2005]骑士精神

Time Limit: 10 Sec  Memory Limit: 162 MB

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

Sample Output

7
-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 */
View Code

 

posted @ 2018-03-22 20:53  大财主  阅读(197)  评论(0编辑  收藏  举报