The Wall Pushers (UVA - 10384)

这里写图片描述

这里写图片描述


这里写图片描述


题意紫书上说的很明确了,不过刚开始那个表示位置的数表示很头疼,后来仔细一看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;
}
水波。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值