最近昀昀学习到了一种新的棋盘游戏,这是一个在一个N×N的格子棋盘上去搞M个棋子的游戏,游戏的规则有下列几条:
- 棋盘上有且仅有一个出口
- 开始时没有哪个棋子在出口,而且所有棋子都不相邻(这里的相邻是指上下左右四个方向)
- M个棋子分别记为1到M
- 每个时刻你可以移动一个棋子向它相邻的四个格子移动一步
- 你需要保证任意时刻棋盘上所有棋子都不相邻
- 只有当前棋盘上编号最小的棋子移动到出口时才能取走改棋子。
- 所有棋子都移走的时候游戏结束
对于一个给定的游戏局面,昀昀最少要多少步才能结束这个游戏呢?
Input
第一行有一个整数T,(T≤200),表示测试数据的组数。
对于每一组数据,第一行是两个整数N,M,其中2≤N≤6, 1≤M≤4。
接下来是一个N×N的棋盘,其中o
代表空格子,x
代表出口,其余的1到M代表这M个棋子。
保证数据是合法的。
Output
对于每一组数据输出最少步数,如果无解输出−1。
Sample input and output
Sample Input | Sample Output |
---|---|
2 3 2 x2o ooo oo1 3 3 xo1 o2o 3oo |
7 -1 |
解题报告
自己也是太年轻。。以为是道大水题,直接上bfs爆搜,果断TLE。。
略思考后显然是A*算法(大水题。。。曼哈顿距离呐)
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <algorithm> 5 #include <cmath> 6 #include <queue> 7 8 9 using namespace std; 10 11 const int Max= 6; 12 int N,M,tid,ttx,tty; 13 char G[Max][Max]; 14 bool vis[36][36][36][36]; 15 16 typedef struct status{ 17 int pos[4],step,pol,f; 18 friend bool operator < (status a,status b) 19 { 20 if (a.step + a.f < b.step + b.f) return false; 21 if (a.step + a.f > b.step + b.f) return true; 22 if (a.step < b.step) return false; 23 else 24 return true; 25 } 26 }; 27 28 priority_queue<status>q; 29 status start; 30 int pol; 31 int dir[4][2] = {0,1,0,-1,1,0,-1,0}; 32 33 /*A* */ 34 int caculatef(status& x){ 35 int result = 0; 36 for(int i = 0;i<M;++i) 37 result += (abs(x.pos[i] / N - ttx) + abs(x.pos[i] % N - tty) ); 38 return result; 39 } 40 41 42 bool judge(status &x){ 43 for(int i = x.pol;i < M;++i) 44 for(int j = i;j < M;++j) 45 if (i != j) 46 { 47 int tx1 = x.pos[i] / N; 48 int ty1 = x.pos[i] % N; 49 int tx2 = x.pos[j] / N; 50 int ty2 = x.pos[j] % N; 51 if (tx1 == tx2 && abs(ty1 - ty2) == 1) return false; 52 else if(ty1 == ty2 && abs(tx1-tx2) == 1) return false; 53 else if(tx1 == tx2 && ty1 == ty2) return false; 54 } 55 return true; 56 } 57 58 59 int bfs(){ 60 memset(vis,false,sizeof(vis)); 61 vis[start.pos[0]][start.pos[1]][start.pos[2]][start.pos[3]] = true; 62 start.step = 0; 63 q.push(start); 64 while(!q.empty()) 65 { 66 status temp = q.top();q.pop(); 67 if(temp.pos[temp.pol] == tid) 68 temp.pol++; 69 if (temp.pol == M) return temp.step; 70 for(int i = temp.pol;i<M;++i) 71 for(int j = 0;j<4;++j) 72 { 73 int newx = temp.pos[i] / N + dir[j][0]; 74 int newy = temp.pos[i] % N + dir[j][1]; 75 if (newx >= N || newx < 0 || newy >= N || newy < 0) continue; 76 int nid = newx * N + newy; 77 status nst = temp; 78 nst.pos[i] = nid; 79 if (!judge(nst)) continue; 80 if (vis[nst.pos[0]][nst.pos[1]][nst.pos[2]][nst.pos[3]] ) continue; 81 vis[nst.pos[0]][nst.pos[1]][nst.pos[2]][nst.pos[3]] = true; 82 nst.step = temp.step + 1; 83 nst.f = caculatef(nst); 84 q.push(nst); 85 } 86 } 87 88 return -1; 89 } 90 91 92 int main(int argc,char * argv[]){ 93 int T; 94 scanf("%d",&T); 95 while(T--) 96 { 97 while(!q.empty()) 98 q.pop(); 99 for(int i = 0;i<4;++i) 100 start.pos[i] = 0; 101 start.pol = 0; 102 scanf("%d%d%*c",&N,&M); 103 for(int i = 0;i<N;++i) 104 gets(G[i]); 105 for(int i = 0;i<N;++i) 106 for(int j = 0;j<N;++j) 107 if(G[i][j] <= '4' && G[i][j] >='1') 108 start.pos[G[i][j] - '1'] = i*N+j; 109 else if(G[i][j] == 'x') 110 tid = i*N + j; 111 ttx = tid / N; 112 tty = tid % N; 113 start.f = caculatef(start); 114 cout << bfs() << endl; 115 } 116 return 0; 117 }
No Pain , No Gain.