码迷,mamicode.com
首页 > 其他好文 > 详细

UESTC_贪吃蛇 CDOJ 709

时间:2015-04-24 23:57:22      阅读:321      评论:0      收藏:0      [点我收藏+]

标签:

相信大家都玩过贪吃蛇游戏吧。

n×m的迷宫中,有着一条长度不超过9的贪吃蛇,它已经将所有的食物吃光了,现在的目标是移动到出口。

它走的时候不能碰到自己的身体,也不能碰到墙壁。(如果贪吃蛇的长度>3并且下一步要走到自己的尾部,是合法的)

问它能不能走到出口,如果能,最少要移动几步?

Input

数据包含多组数据,请读入到文件末尾EOF

每组数据第一行包含两个整数n,m(1n,m15)代表迷宫的大小。

接下来n行,每行包含一个长度为m的字符串,来表示迷宫。

字符串中仅包含.#@1 ~ 9.代表空地 # 代表墙 数字一定是1k 连续的k个数字,代表贪吃蛇,1代表它的头,k代表它的尾,数据保证数字i一定和数字i+1在迷宫中相邻。 @ 代表出口。

Output

对于每组数据,先输出Case #i: ,i为当前数据组数。

接下来一个数,代表贪吃蛇最少需要移动的步数,若无法移动出去输出-1

 

解题报告

主要是判重问题

肯定不能vis[15][15].....x9

内存依然爆炸,其实大部分都是没有使用的,因此我们考虑到

蛇的每截身体较于前面一截只有 4 种状态,我们用4进制来压缩蛇的身体,这样就能存下了,注意蛇头可以移动到最后一截身体所在的位置.

 

 

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int Max = 15;
char G[Max+2][Max+2];
bool vis[15][15][9850];
int  R,C,targetx,targety,n;
// n is snake-body num
int  dir[4][2] ={-1,0,1,0,0,-1,0,1};
int  caculate[8] ={1,3,9,27,81,243,729,2187};
typedef struct status
{
  int x[9];
  int y[9];
  int step;    
};


status ori;
status thisq[1000000];


int getturn(int x,int y,int x0,int y0){
if (x - x0 == 1) return 0;
if (x - x0 == -1) return 1;
if (y - y0 == 1) return 2;
if (y - y0 == -1) return 3;
printf("Error at get turn!\n");        
}

int getcode(status& x){
int buffer[12];
int code = 0;
for(int i = 1;i<n;++i)
 code += getturn(x.x[i],x.y[i],x.x[i-1],x.y[i-1]) * caculate[i-1];
return code;
}


bool judge(status& x){
int tx = x.x[0];
int ty = x.y[0];
for(int i = 1;i<n;++i)
 if(x.x[i] == tx && x.y[i] == ty)
  return false;
return true;    
}

bool dfs1(int x,int y){
int front = 0,rear = 0;
int q[8000][2];
bool evis[15][15];
memset(evis,false,sizeof(evis));
evis[x][y] = true;
q[rear][0] = x;
q[rear++][1] = y;
while(front < rear)
{
    int tx = q[front][0];
    int ty = q[front++][1];
    if (tx == targetx && ty == targety) return true;
    for(int i = 0;i<4;++i)
     {
         int newx = tx + dir[i][0];
         int newy = ty + dir[i][1];
         if (!evis[newx][newy] && G[newx][newy] != # && newx < R && newx >=0 && newy < C && newy >=0)
          {
              q[rear][0] = newx;
              q[rear++][1] = newy;
              evis[newx][newy] = true;
          }
      }
}



return false;    
}    



int dfs(){
int front = 0,rear = 0;
ori.step = 0;
thisq[rear++] = ori;
vis[ori.x[0]][ori.y[0]][getcode(ori)] = true;    
while(front < rear)
{
 int tx = thisq[front].x[0];
 int ty = thisq[front].y[0];
 int step = thisq[front].step;
 if (tx == targetx && ty == targety) return step;
 for(int i = 0 ;i < 4;++i)
 {
     int newx = tx + dir[i][0];
     int newy = ty + dir[i][1];
     int newstep = step+1;
     if (newx >= R || newx < 0 || newy >=C || newy < 0 || G[newx][newy] == #) 
      continue;
     status newst;
     newst.x[0] = newx;
     newst.y[0] = newy;
     newst.step = step + 1;
     for(int j=1;j<n;++j)
      {
          newst.x[j] = thisq[front].x[j-1];
          newst.y[j] = thisq[front].y[j-1];
      }
    if (!vis[newst.x[0]][newst.y[0]][getcode(newst)] && judge(newst))
     {
         thisq[rear++] = newst;
         vis[newst.x[0]][newst.y[0]][getcode(newst)] = true;
     }
 }
 
 front++;
}

return -1;
}


bool input(){
while(scanf("%d%d%*c",&R,&C)==2)
{
 n = 0;
 memset(vis,false,sizeof(vis));
 for(int i = 0;i<R;++i)
  gets(&G[i][0]);
 for(int i = 0;i<R;++i)
  for(int j = 0;j<C;++j)
   if(G[i][j] == @)
   {
       targetx = i;
       targety = j;
   }    
   else if(G[i][j] <= 9 && G[i][j] >= 1)
   {
       ori.x[G[i][j] - 1] = i;
       ori.y[G[i][j] - 1] = j;
       n ++ ;
   }
 return true;
}
return false;
}


int main(int argc,char * argv[]){
int T = 1;
while(input() == true)
{
 if(!dfs1(ori.x[0],ori.y[0]))
  {
      cout << "Case #"<< T++ <<": -1" <<endl;
      continue;
  }
 int ans = dfs();
 cout << "Case #"<< T++ <<": "<< ans <<endl;
}
return 0;    
}

 

 

 

UESTC_贪吃蛇 CDOJ 709

标签:

原文地址:http://www.cnblogs.com/Xiper/p/4455053.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!