题解 P1126 【机器人搬重物】

GNAQ

2017-05-01 10:37:38

Solution

```cpp #include<cstdio> #include<iostream> #include<cmath> #include<cstring> #include<string> #include<queue> #include<algorithm> using namespace std; int main() { bool mapx[100][100]; //Map queue<int> quex,quey,quedir; //Queue of Line,Row & Direction int sx,sy,ex,ey,dir,n,m; char dx; int timex[100][100][4]={0}; //HASH int cachex,cachey,cachedir,cachedir2,cachego=0; //Caches int wayx[4]={-1,0,1,0},wayy[4]={0,1,0,-1}; //Direction Table memset(mapx,true,sizeof(mapx)); scanf("%d%d",&n,&m); for (int i=0;i<n;i++) { for (int j=0;j<m;j++) { scanf("%d",&mapx[i][j]); } } scanf("%d%d%d%d %c",&sx,&sy,&ex,&ey,&dx);//可以在%c前面加个空格来吸收读入的时候的空格 switch(dx)//把字符形式的坐标转化成数字(我使用了方向表 直接用dir的值查表,再乘以前进的步数,就是坐标变化量 !) { case 'N': dir=0; break; case 'E': dir=1; break; case 'S': dir=2; break; case 'W': dir=3; break; } sx--; sy--; ex--; ey--;//处理成数组下标的形式(数组下标从0开始) timex[sx][sy][dir]=0;/*初始化HASH*/ quex.push(sx); quey.push(sy); quedir.push(dir); //初始值入队列 while (quex.size()>0) { cachex=quex.front(); cachey=quey.front(); cachedir=quedir.front(); cachego=1; //队首值缓存一下,便于处理 if (cachex==ex && cachey==ey) //采用判断队首值的方法,起点和终点重合就不用加特判了 { printf("%d",timex[cachex][cachey][cachedir]); return 0; } for (int i=1;i<=5;i++)//五种命令 { if (i<=3/*如果是前三种*/ && cachex+wayx[cachedir]*i>=0 && cachex+wayx[cachedir]*i<n-1 && cachey+wayy[cachedir]*i>=0 && cachey+wayy[cachedir]*i<m-1/*没有越界*/ && cachego==i/*前面的移动成立*/) if (mapx[cachex+wayx[cachedir]*i][cachey+wayy[cachedir]*i]==0 && mapx[cachex+wayx[cachedir]*i+1][cachey+wayy[cachedir]*i]==0 && mapx[cachex+wayx[cachedir]*i+1][cachey+wayy[cachedir]*i+1]==0 && mapx[cachex+wayx[cachedir]*i][cachey+wayy[cachedir]*i+1]==0) //移动之后不越界 新的xy坐标是i(i同时代表了前进的步数 有1、2、3步)乘以方向表里目前的方向前进一步的xy坐标变化量 { cachego++;//前一步不能走,有一种情况是Hash表的这个位置已经存在一个更短的耗时。但这不代表这一步不能走,也不代表走这一步的耗时不是最短的(因为方向问题) if (timex[cachex+wayx[cachedir]*i][cachey+wayy[cachedir]*i][cachedir]==0) //Hash表内这个位置没有被访问过(如果访问过,则Hash表内一定是一个最短的耗时 { timex[cachex+wayx[cachedir]*i][cachey+wayy[cachedir]*i][cachedir]=timex[cachex][cachey][cachedir]+1;//根据结点所在层数写入Hash表 quex.push(cachex+wayx[cachedir]*i); quey.push(cachey+wayy[cachedir]*i); quedir.push(cachedir);//入队列 } } if (i==4) //Left { cachedir2=cachedir-1; if (cachedir2==-1) cachedir2=3;//如果由North转到West,就重置方向缓存 if (timex[cachex][cachey][cachedir2]==0) //Hash表内这个位置没有被访问过(如果访问过,则Hash表内一定是一个最短的耗时 { timex[cachex][cachey][cachedir2]=timex[cachex][cachey][cachedir]+1;//根据结点所在层数写入Hash表 quex.push(cachex); quey.push(cachey); quedir.push(cachedir2);//入队列 } } if (i==5) //Right 同上 { cachedir2=cachedir+1; if (cachedir2==4) cachedir2=0; if (timex[cachex][cachey][cachedir2]==0) { timex[cachex][cachey][cachedir2]=timex[cachex][cachey][cachedir]+1; quex.push(cachex); quey.push(cachey); quedir.push(cachedir2); } } } quex.pop(); quey.pop(); quedir.pop();//出队列 } cout<<-1<<endl; return 0; } ```