hdu 5335 Walk Out



官方解析:

If we require that the explorer could only move downward or rightward, this problem will be easier: the length of the binary number will always be n+m-1, and we could work this out length by length. At first, the length of the binary number is 1 (at the entrance). If the entrance is adjacent to some 0, the explorer would definitely go to these 0s; otherwise, he could only go to 1s. In either occasion, there will be several possible positions, but the binary numbers will always be same. After getting the minimum value and the possible positions of this length, we could walk the next step, by finding the adjacent 0s with this length's possible position. Finally, we could arrive at the exit.

  Now return to the original problem: the explorer could move in any direction. However, is moving for long optimal?  Absolutely not. A longer binary number is always larger than a short one, but do not forget the preceding 0s. In fact. The explorer could walk on any number of 0s at first, and still keep the binary number equal to 0. Therefore, we need to find all the positions that are connected by 0s with the entrance. The explorer would walk on these positions freely, and then step on the first 1. He should make the first 1 nearest to the exit. After that, we could use the solution in the first paragraph to solve the whole problem.



相应的解法:

#include <iostream>  
#include <queue>  
#include <cstdio>  
#include <cstring>  
using namespace std;  
const int inf = 0x3f3f3f3f;  
int mark[1010][1010], n, m, cnt; // cnt 表示可行点的个数;  
char s[1010][1010];  
struct node{  
    int x, y;  
}_n[2010];  
void init(){  
    scanf("%d%d", &n, &m);  
    for(int i = 0; i < n; ++i){  
        scanf("%s", s[i]);  
    }  
}  
int dir[4][2] = {{1, 0}, {0, 1}, {0, -1}, {-1, 0}};  
void find_start(){  
    memset(mark, -1, sizeof(mark));  
    if(s[0][0] == '1'){  
        cnt = 1;  
        _n[0].x = 0;  
        _n[0].y = 0;  
        return ;  
    }  
    queue<node> q;  
    node cur, next;  
    cur.x = 0, cur.y = 0;  
    q.push(cur);  
    while(!q.empty()){  
        cur = q.front();  
        q.pop();  
        for(int i = 0; i < 4; ++i){  
            next.x = cur.x + dir[i][0];  
            next.y = cur.y + dir[i][1];  
            if(next.x < 0 || next.y < 0 || next.x >= n || next.y >= m)  
                continue;  
            if(mark[next.x][next.y] != -1)  
                continue;  
            if(s[next.x][next.y] == '1')  
                mark[next.x][next.y] = 1;  
            if(s[next.x][next.y] == '0'){  
                mark[next.x][next.y] = 0;  
                q.push(next);  
            }  
        }  
    }  
    if(mark[n - 1][m - 1] == 0){  
        cnt = 0;  
        return ;  
    }  
    cnt = 0;  
    int key = inf;  
    for(int i = 0; i < n; ++i){  
        for(int j = 0; j < m; ++j){  
            if(mark[i][j] == 1){  
                int x = n + m - i - j - 2; // 走到(n-1, m-1);  
                if(x < key){  
                    cnt = 0;  
                    _n[cnt].x = i;  
                    _n[cnt++].y = j;  
                }  
                if(x == key){  
                    _n[cnt].x = i;  
                    _n[cnt++].y = j;  
                }  
            }  
        }  
    }  
}  
void bfs(){  
    queue<node> q1, q2;  
    node cur, next;  
    memset(mark, 0, sizeof(mark));  
    for(int i = 0; i < cnt; ++i){  
        mark[_n[i].x][_n[i].y] = 1;  
        q1.push(_n[i]);  
    }  
    printf("1");  
    if(mark[n - 1][m - 1] == 1)  
        return ;  
    while(1){  
        int flag = 1;   // 找到0(flag = 0) 没找到flag = 1;  
        while(!q1.empty()){  
            cur = q1.front();  
            q1.pop();  
            for(int i = 0; i < 2; ++i){  
                next.x = cur.x + dir[i][0];  
                next.y = cur.y + dir[i][1];  
                if(next.x < 0 || next.x >= n || next.y < 0 || next.y >= m)  
                    continue;  
                if(!mark[next.x][next.y]){  
                    mark[next.x][next.y] = 1;  
                    if(s[next.x][next.y] == '0')  
                        flag = 0;  
                    q2.push(next);  
                }  
            }  
        }  
        printf("%d", flag);  
        if(mark[n - 1][m - 1] == 1)  
            break;  
        while(!q2.empty()){  
            cur = q2.front();  
            q2.pop();  
            if(flag == 0){  
                if(s[cur.x][cur.y] == '0')  
                    q1.push(cur);  
            }  
            else  
                q1.push(cur);  
        }  
    }  
}  
int main()  
{  
    int T;  
    cin >> T;  
    while(T--){  
        init();  
        find_start();  
        if(cnt == 0)  
            printf("0\n");  
        else{  
            bfs();  
            printf("\n");  
        }  
    }  
    return 0;  
}  

我的AC代码:

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1010;
struct node
{
    int x, y;
};
char a[maxn][maxn];
bool vis[maxn][maxn];
int dir[4][2] = {1,0, 0,1, -1,0, 0,-1};
int x, y, n, m;
bool check (int x, int y)
{
    if (x<0 || y<0 || x>=n || y>=m)
        return false;
    return true;
}
void bfs ()
{
    node p, q;
    p.x = x, p.y = y;
    queue <node> Q;
    Q.push (p);
    while (!Q.empty())
    {
        p = Q.front();
        Q.pop();
        for (int i=0; i<4; i++)
        {
            q.x = p.x + dir[i][0];
            q.y = p.y + dir[i][1];
            if (check(q.x, q.y) && !vis[q.x][q.y])
            {
                vis[q.x][q.y] = true;
                if (a[q.x][q.y] == '0')
                    Q.push (q);
                if (x + y < q.x + q.y)
                    x = q.x, y = q.y;
            }
        }
    }
}
int main ()
{
    int t;
    scanf ("%d", &t);
    while (t --)
    {
        memset (vis, false, sizeof(vis));
        vis[0][0] = true;
        scanf ("%d %d", &n, &m);
        for (int i=0; i<n; i++)
            scanf ("%s", a[i]);
        x = y = 0;
        if (a[x][y] == '0')
            bfs ();
        if (a[x][y] == '0')
            putchar('0');
        else
        {
            bool nowflag = false;
            putchar ('1');
            for (int i=x+y; i<n+m-2; i++)
            {
                bool flag = false;
                for (x=0; x<=i; x++)
                {
                    y = i - x;
                    if (!check(x, y) || !vis[x][y])
                        continue;
                    if (nowflag && a[x][y]=='1')
                        continue;
                    for (int j=0; j<2; j++)
                    {
                        int xx = x + dir[j][0];
                        int yy = y + dir[j][1];
                        if (!check(xx,yy))
                            continue;
                        vis[xx][yy] = true;
                        if (a[xx][yy] == '0')
                            flag = true;
                     }
                }
                nowflag = flag;
                putchar (flag?'0':'1');
            }
        }
        puts("");
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值