最近昀昀学习到了一种新的棋盘游戏,这是一个在一个N×N的格子棋盘上去搞M个棋子的游戏,游戏的规则有下列几条:

  1. 棋盘上有且仅有一个出口
  2. 开始时没有哪个棋子在出口,而且所有棋子都不相邻(这里的相邻是指上下左右四个方向)
  3. M个棋子分别记为1M
  4. 每个时刻你可以移动一个棋子向它相邻的四个格子移动一步
  5. 你需要保证任意时刻棋盘上所有棋子都不相邻
  6. 只有当前棋盘上编号最小的棋子移动到出口时才能取走改棋子。
  7. 所有棋子都移走的时候游戏结束

对于一个给定的游戏局面,昀昀最少要多少步才能结束这个游戏呢?

Input

第一行有一个整数T,(T200),表示测试数据的组数。

对于每一组数据,第一行是两个整数N,M,其中2N61M4

接下来是一个N×N的棋盘,其中o代表空格子,x代表出口,其余的1M代表这M个棋子。

保证数据是合法的。

Output

对于每一组数据输出最少步数,如果无解输出1

Sample input and output

Sample InputSample 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 }

 

 

 

posted on 2015-04-29 23:45  天心散人  阅读(358)  评论(0编辑  收藏  举报