题意紫书上说的很明确了,不过刚开始那个表示位置的数表示很头疼,后来仔细一看1,2,4,8,这些数字不就是正好可以看为二进制么,这样的话就很有思路了。这里我们就用到了神奇的位运算。
看代码前先学习一下位运算欧。。。。。。。。。。。。
其实题目是一个迭代加深搜索,就是处理推墙和处理一个点的四个方向比较麻烦,具体思想在代码中注释。
上代码:
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
using namespace std;
int op[10][10];
int nex_t[4][2]={ {0,-1},{-1,0},{0,1},{1,0} }; // 四个方向
int vis[10][10];
char lu[5]="WNES"; //与nex_t中的对应。
// 2
//1 4
// 8
int a[4]={1,2,4,8}; // 四个方向,如上图
int b[4]={4,8,1,2}; //用来表示推墙之后对其他位置的影响,
//可以自己做个图,看一下推墙之后三个点的变化,就可以总结规律
char luu[1000]; // 保存路径
bool dfs(int x,int y,int d,int max_d)
{
if( d==max_d ) // 判断
{
if( x==0||y==0||x==5||y==7 ) return true; // 如果人已经走出地图,那么说明他已经成功
else return false;
}
int x1,x2,y1,y2;
vis[x][y] = 1;
for(int i=0;i<4;i++)
{
x1 = x + nex_t[i][0];
y1 = y + nex_t[i][1];
x2 = x1+ nex_t[i][0];
y2 = y1+ nex_t[i][1]; //推墙之后影响的两个点(x1,y1),(x2,y2);
if(vis[x1][y1])continue;
if((op[x][y]&a[i])==0) //与运算,判断该点的这条边是不是有墙,具体可以百度与运算学习一下。
{
luu[d] = lu[i];
if(dfs(x1,y1,d+1,max_d)) {vis[x][y]=0;return true;}
}else if( (op[x1][y1]&a[i])==0 )
{
luu[d] = lu[i];
op[x][y] -= a[i];
op[x1][y1] += a[i] - b[i];
op[x2][y2] += b[i];
if(dfs(x1,y1,d+1,max_d))
{
vis[x][y] = 0;
op[x][y] += a[i];
op[x1][y1] -= a[i] - b[i];
op[x2][y2] -= b[i];
return true;
}
op[x][y] += a[i];
op[x1][y1] -= a[i] - b[i];
op[x2][y2] -= b[i];
}
}
vis[x][y] = 0; //回溯
return false;
}
int main()
{
for(int i=1;i<=6;i++)
op[0][i]=2,op[5][i]=8;
for(int i=1;i<=4;i++)
op[i][0]=1,op[i][7]=4; // 处理边界,因为题目说如果墙已经在边界上这堵墙就没法推动
// 处理边界之后在后面的dfs中就方便了,因为不用特判边界了。
int x, y;
while(scanf("%d %d",&y, &x)!=EOF)
{
if(x==0&&y==0)break;
for(int i=1;i<=4;i++)
for(int j=1;j<=6;j++)
scanf("%d", &op[i][j]);
memset(vis,0,sizeof(vis));
for(int maxd=0; ;maxd++)
{
if(dfs(x,y,0,maxd))break;
}
for(int i=0;i<maxd;i++)
printf("%c",luu[i]);
printf("\n");
}
return 0;
}
水波。