DFS-hdu-2821-Pusher

来源:互联网 发布:蓝桥杯单片机 编辑:程序博客网 时间:2024/06/07 00:18

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=2821

题目意思:

给一个n*n的矩阵,里面有些位置是空的,有些位置有箱子(a代表一个箱子,b代表两个,依此类推)。让你选择一个空位置作为起点,然后每步选择一个方向(上,下,左,右)走,直到碰到箱子为止,然后将此位置的箱子移走一个,剩下的箱子全部合并到下一位置。要求:必须与箱子隔超过1个位置的时候才能移。

求一个开始位置使得能够移除所有的箱子,并输出行走路线。

经数据检测两点注意:1、不含边缘位置超过一个箱子的情况,2、保证有解。

解题思路:

枚举开始位置,DFS深搜,有一条路径能全部移走箱子,则输出。

注意保存回溯现场(不要用全局变量来保存现场,因为在递归调用的时候会覆盖原来保存的现场,wa了好几次)。

代码:

#include<iostream>#include<cmath>#include<cstdio>#include<cstdlib>#include<string>#include<cstring>#include<algorithm>#include<vector>#include<map>#include<set>#include<stack>#include<list>#include<queue>#define eps 1e-6#define INF 0x1f1f1f1f#define PI acos(-1.0)#define ll __int64#define lson l,m,(rt<<1)#define rson m+1,r,(rt<<1)|1//#pragma comment(linker, "/STACK:1024000000,1024000000")using namespace std;/*freopen("data.in","r",stdin);freopen("data.out","w",stdout);*/char save[30][30],save1[30][30];int c,r,dir[4][2]={{-1,0},{0,1},{1,0},{0,-1}};int lim,cnt;char di[4]={'U','R','D','L'};struct Inf{   int x,y;}s;bool iscan(Inf & tt,int dd){   int xx=tt.x+dir[dd][0],yy=tt.y+dir[dd][1];   if(xx<0||xx>=r||yy<0||yy>=c) //下一步出界了,不行      return false;   if(save1[xx][yy]!='.') //下一步就是箱子不行      return false;   while(save1[xx][yy]=='.') //在该方向走,直到靠近箱子为止   {      xx=xx+dir[dd][0],yy=yy+dir[dd][1];      if(xx<0||xx>=r||yy<0||yy>=c)//走出去了,不行         return false;   }   if(save1[xx][yy]=='a')//该位置只有一个箱子   {      cnt++;      save1[xx][yy]='.';      tt.x=xx,tt.y=yy;      return true;   }   else   //该位置有多个箱子   {      int x=xx+dir[dd][0],y=yy+dir[dd][1];      if(x<0||x>=r||y<0||y>=c) //边缘有多个箱子的情况      {         //cnt++;         //tt.x=xx,tt.y=yy;         //save1[xx][yy]=save1[xx][yy]-1;         //return true; //两种写法都可以,其他写法也行,因为测试数据中不存在这种情况         return false;      }      cnt++;      tt.x=xx,tt.y=yy;      if(save1[x][y]!='.') //下一位置如果不是.的话,直接合并         save1[x][y]=save1[x][y]+save1[xx][yy]-'a';//注意-'a'      else    //下一位置是.的话,直接拿过来         save1[x][y]=save1[xx][yy]-1;      save1[xx][yy]='.';      return true;   }}bool flag;string an;void dfs(Inf cur,string ans){   if(flag) //已找到一条路径      return ;   char tt[30][30];//注意保存现场时要用局部变量   for(int i=0;i<4;i++) //沿四个方向走   {      memcpy(tt,save1,sizeof(save1));      Inf tmp=cur;      int temp=cnt; //便于回溯的时候,其他没有改变      /*if(test)      {         for(int j=0;j<r;j++)            printf("%d %s\n",j,save1[j]);      }*/      if(!iscan(tmp,i))         continue;     /* if(test)      {         printf("%d %d->%d %d cnt:%d\n",cur.x,cur.y,tmp.x,tmp.y,cnt);         putchar('\n');         for(int j=0;j<r;j++)            printf("%d %s\n",j,save1[j]);      }*/      string tm=ans;      tm+=di[i];      if(cnt==lim) //找到了一条路径能全部移完      {         an=tm;         flag=true;         return ;      }      dfs(tmp,tm);      cnt=temp;  //回溯      memcpy(save1,tt,sizeof(tt));   }}int main(){   while(~scanf("%d%d",&c,&r))   {      lim=0;      for(int i=0;i<r;i++)      {         scanf("%s",save[i]);         for(int j=0;j<c;j++)            if(save[i][j]!='.')               lim+=(save[i][j]-'a'+1); //统计箱子个数      }      //putchar('\n');      flag=false;      for(int i=0;i<r&!flag;i++)         for(int j=0;j<c&&!flag;j++)         {            if(save[i][j]!='.') //枚举开始位置,注意开始位置不为               continue;            s.x=i,s.y=j;            cnt=0;            memcpy(save1,save,sizeof(save));            dfs(s,"");            if(flag)            {               printf("%d\n%d\n",i,j);               cout<<an<<endl;            }         }   }   return 0;}



原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 土豆发青中毒怎么办吗 土豆中毒呕吐后怎么办 土豆没熟中毒怎么办 吃洋芋中毒了怎么办? 脸上出毒气疙瘩怎么办 吃了土豆呕吐怎么办 煤烟中毒后头疼怎么办 身上长毒气疙瘩怎么办 宝宝肚子寒疼怎么办 小孩腹胀腹痛不消化怎么办 颠茄片服用过量怎么办 狗吃番茄拉肚子怎么办 颠茄片中毒了怎么办 拉肚子半个月怎么办啊 肚子里有细菌怎么办 文珠兰叶子黄了怎么办 文殊兰叶子太长怎么办 桑叶牡丹有虫子怎么办? 米兰花叶子枯萎怎么办 一品红叶子不红怎么办 兰花叶有白点怎么办 旱莲花叶子黄怎么办 旱莲花叶子发黄怎么办 长寿冠叶子枯萎怎么办 长寿花枯萎了怎么办 竹节海棠植株发软怎么办 竹节海棠烂根怎么办 倒挂金钟晒伤了怎么办 长寿花已经徒长怎么办 夏天长寿花徒长怎么办 吊金钟叶子蔫了怎么办 四季海棠长虫子怎么办 小金鱼花不开花怎么办 杜鹃花浇肥大了怎么办 四季海棠烂叶子怎么办 竹节海棠叶子干枯怎么办 月月菊花花朵发黑怎么办 枯萎的四季海棠怎么办 夏天蟹爪兰叶子发软怎么办 夏天蟹爪兰掉叶子该怎么办 天竺葵木质化了怎么办