【题意】:给出一个n*m的国际象棋棋盘 (1 ≤ n, m ≤ 15),棋盘里面只有四种棋子。
               * 白色的皇 可以向任意周围八格移动一格
               R 黑色的车 可以横着或竖着移动任意格
               K 黑色的马  移动“日”字
               B 黑色的象  可以斜着走任意格
               已知棋盘最多有15个棋子,有且只有一个白色的皇, 且黑棋在吃不到皇的情况下是不会移动的。
               问,在不被吃的情况下,皇最少用多少步可以吃光所有的黑棋。

【题解】:考虑到最多只有15个棋子,可以进行状态压缩的bfs。这里有个trick就是,象和车可能会被其他棋子挡着而吃不到皇。

【代码】:
  1 #include "iostream"
  2 #include "cstdio"
  3 #include "cstring"
  4 #include "queue"
  5 using namespace std;
  6 int r, c, sx, sy;
  7 int cnt;
  8 char maz[20][20];
  9 int maze[20][20];
 10 bool visit[20][20][40000];
 11 int dir[][2= {0110-100-11-1-1111-1-1};
 12 int kdir[][2= {-2-1-21212-1121-2-12-1-2};
 13 int bdir[][2= {1-111-1-1-11};
 14 int rdir[][2= {0110-100-1};
 15 struct Node {
 16     int x, y, ti, mask;
 17     Node(){}
 18     Node(int _x, int _y, int _ti, int _mask) {
 19         x = _x, y = _y, ti = _ti, mask = _mask;
 20     }
 21 };
 22 
 23 struct Piece {
 24     int x, y, type;
 25     Piece(){}
 26     Piece(int _x, int _y, int _type) {
 27         x = _x, y = _y, type = _type;
 28     }
 29 }p[20];
 30 
 31 bool check(int x, int y) {
 32     if(x >= 1 && x <= r && y >= 1 && y <= c) return true;
 33     return false;
 34 }
 35 
 36 bool IsEat(int x, int y, int mask) {
 37     //Knight
 38     for(int i = 0; i < 8; i++) {
 39         int xx = x + kdir[i][0], yy = y + kdir[i][1];
 40         int tmp = maze[xx][yy];
 41         if(!check(xx, yy)) continue;
 42         if(tmp >= 0 && !(mask & (1 << tmp)) && p[tmp].type == 0return true;
 43     }
 44     //Bishop
 45     for(int i = 0; i < 4; i++) {
 46         int xx = x + bdir[i][0], yy = y + bdir[i][1];
 47         int tmp = maze[xx][yy];
 48         while(check(xx, yy)) {
 49             if(tmp >= 0 && !(mask & (1 << tmp))) {
 50                 if(p[tmp].type == 1return true;
 51                 else break;
 52             } else xx += bdir[i][0], yy += bdir[i][1], tmp = maze[xx][yy];
 53         }
 54     }
 55     //Rook
 56     for(int i = 0; i < 4; i++) {
 57         int xx = x + rdir[i][0], yy = y + rdir[i][1];
 58         int tmp = maze[xx][yy];
 59         while(check(xx, yy)) {
 60             if(tmp >= 0 && !(mask & (1 << tmp))) {
 61                 if(p[tmp].type == 2return true;
 62                 else break;
 63             } else xx += rdir[i][0], yy += rdir[i][1], tmp = maze[xx][yy];
 64         }
 65     }
 66     return false;
 67 }
 68 
 69 int bfs() {
 70     queue<Node> que;
 71     memset(visit, falsesizeof(visit));
 72     visit[sx][sy][0= true;
 73     que.push(Node(sx, sy, 00));
 74     while(!que.empty()) {
 75         Node now = que.front();
 76         que.pop();
 77         if(now.mask == (1 << cnt) - 1return now.ti;
 78         for(int i = 0; i < 8; i++) {
 79             int nx = now.x + dir[i][0], ny = now.y + dir[i][1], mask = now.mask;
 80             if(!check(nx, ny)) continue;
 81             int tmp = maze[nx][ny];
 82             if(tmp >= 0) mask |= (1 << tmp);
 83             if(visit[nx][ny][mask]) continue;
 84             if(IsEat(nx, ny, mask)) continue;
 85             que.push(Node(nx, ny, now.ti + 1, mask));
 86             visit[nx][ny][mask] = true;
 87         }
 88     }
 89     return -1;
 90 }
 91 
 92 int main() {
 93     while(~scanf("%d%d"&r, &c)) {
 94         cnt = 0;
 95         memset(maze, -1sizeof(maze));
 96         for(int i = 1; i <= r; i++) scanf("%s"&maz[i][1]);
 97         for(int i = 1; i <= r; i++) {
 98             for(int j = 1; j <= c; j++) {
 99                 if(maz[i][j] == '.'continue;
100                 if(maz[i][j] == '*') sx = i, sy = j;
101                 else if(maz[i][j] == 'K') {
102                     maze[i][j] = cnt, p[cnt++= Piece(i, j, 0);
103                 } else if(maz[i][j] == 'B') {
104                     maze[i][j] = cnt, p[cnt++= Piece(i, j, 1);
105                 } else maze[i][j] = cnt, p[cnt++= Piece(i, j, 2);
106             }
107         }
108         int ans = bfs();
109         cout << ans << endl;
110     }
111     return 0;
112 }