hdu 5335 Walk Out

Walk Out

这题目的大致意思是一个人在n*m的迷宫里,一开始在(1,1)处,要走到(n,m)处,他每走一格都会记录下这格格子上的数,格子上不是1就是0,现在要使他记下来的这串二进制数最小。

考试的时候一直想着用dfs,然后一直爆内存,然后一直钻牛角尖,想着把数组开小点,因为就超了没多少内存,结果浪费了好长时间0.0

现在想想当时也是蠢,用bfs不就行了0.0

我的想法是

有这样一个迷宫

001
111
101
先去遍历,将从(1,1)点出发所有可以走到的0点走一遍,并标记,并得出这些点中坐标之和(即i+j)最大的一些点,然后从这些点开始走,每次只能向右或向下走,将同一时间会走到的格子都走一下,有0只走0,没有0就只能走1。

比如上述的例子中,先遍历0点

001
111
101
红色表示遍历过了, 绿色表示要开始走的点

001
111
101
蓝色的点表示我下一步可以走的,有0所以我走0,不走1

001
111
101

之后最后一步走到最后一格就完成了

001
111
101

所以说是101

代码附上,写的有点难看0.0

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
using namespace std;
struct list{
   public:
       int x;
       int y;
};
const int MAXN=1012;
char a[MAXN][MAXN];
list b[MAXN*MAXN];
bool p[MAXN][MAXN];
int i,j,num,n,m,l,r,p1,rr,pp;
list h;
void doit(int x,int y)//寻找下个可去点的
{
    if (x+1<=n&&!p[x+1][y])
    {
        r++;
        b[r].x=x+1;
        b[r].y=y;
        p[x+1][y]=1;
    }
    if (y+1<=m&&!p[x][y+1])
    {
        r++;
        b[r].x=x;
        b[r].y=y+1;
        p[x][y+1]=1;
    }
}
void sc(int x,int y)//用来遍历与(1,1)所有连着的0点
{
    if (x>0&&x<=n&&y>0&&y<=m&&a[x][y]=='0'&&p[x][y]==0)
    {
        p[x][y]=1; r++;
        b[r].x=x; b[r].y=y;
        if (x+y>num) num=x+y;
    }
}
int main()
{
    int T;
    string t1,t;
    int i,l;
    cin>>T;
    for (int I=1;I<=T;I++)
    {
        pp=0;
        memset(p,0,sizeof(p));
        scanf("%d%d",&n,&m);
        for (i=1;i<=n;i++){ getchar();
            for (j=1;j<=m;j++)
            {
                scanf("%c",&a[i][j]);
            }
        }
        num=2; r=0;
        if (a[1][1]=='0')
        {
            r=1; l=1; b[1].x=1; b[1].y=1; p[1][1]=1;
            while (l<=r)
            {
                rr=r;
                for (i=l;i<=rr;i++)
                {
                    h=b[i];
                    sc(h.x+1,h.y);
                    sc(h.x-1,h.y);
                    sc(h.x,h.y-1);
                    sc(h.x,h.y+1);
                }
                l=rr+1;
            }
            r=0;
            for (i=1;i<=n;i++)
            if (num-i>0&&num-i<=m&&p[i][num-i]==1)
            {
                doit(i,num-i);
             }
        }
        else { r=1; b[r].x=1; b[r].y=1; p[1][1]=1;}
            l=1;
        while (l<=r)
        {
            rr=r; p1=0;
            for (i=l;i<=rr;i++)
                if (a[b[i].x][b[i].y]=='0')//有0走0
            {
                doit(b[i].x,b[i].y);
                p1=1;
            }
            if (p1==0)//没0 走1
            {
                cout<<1; pp=1;
                for (i=l;i<=rr;i++)
                {
                   doit(b[i].x,b[i].y);
                }
            } else cout<<0;
            l=rr+1;
        }
        if (pp==0) cout<<0;
        cout<<endl;
    }
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值