hdu5335 Walk Out (bfs + 斜线递推)

Walk Out
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 5323 Accepted Submission(s): 1092

Problem Description
In an n∗m maze, the right-bottom corner is the exit (position (n,m) is the exit). In every position of this maze, there is either a 0 or a 1 written on it.

An explorer gets lost in this grid. His position now is (1,1), and he wants to go to the exit. Since to arrive at the exit is easy for him, he wants to do something more difficult. At first, he’ll write down the number on position (1,1). Every time, he could make a move to one adjacent position (two positions are adjacent if and only if they share an edge). While walking, he will write down the number on the position he’s on to the end of his number. When finished, he will get a binary number. Please determine the minimum value of this number in binary system.

Input
The first line of the input is a single integer T (T=10), indicating the number of testcases.

For each testcase, the first line contains two integers n and m (1≤n,m≤1000). The i-th line of the next n lines contains one 01 string of length m, which represents i-th row of the maze.

Output
For each testcase, print the answer in binary system. Please eliminate all the preceding 0 unless the answer itself is 0 (in this case, print 0 instead).

Sample Input
2
2 2
11
11
3 3
001
111
101

Sample Output
111
101

这道题浪费了好长时间,爆完内存,然后超时,接着无数的wa,心累。。。。
刚开始思路,因为如果起始点如果是1的话,那么得出的二进制串的长度一定是确定的,如果s[0][0] == ‘0’的话,先搜索0,找到一串0后的第一个1的坐标离终点最近,也就是max(x + y),这样的坐标点有多个,有个特点就是这些点位于同一条斜线上。。。。
如果s[0][0] == ‘1’,直接进入下一步;
接着就和s[x][y] = = ‘1’到终点即可,如果这里用宽搜,标记的话会出错,因为每个点会忘右边和下边两个方向进行搜索,一个点搜过了,标记为true,另一个点再来的话就搜不到了,如果此时得到的序列更优就不行了,所以需要换一种搜索策略或者直接从上一步宽搜得出的斜线开始往下递推:
递推规则:
对当前斜线上的点进行遍历,如果当前点左边或上边的点被标记为可达点,则将当前标记为可达点,如果这些点中出现0,则需要把标为1的点填成-1(不可达);注:0,1(可达);
只要斜线上出现过0,把0加在最后的结果中,如果没有0存在,把1加在最后的结果中。。

注:还有一点,写宽搜的时候居然忘了加标记。。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<string>
using namespace std;
typedef long long LL;
const int inf = 0x3f3f3f3f;
#define pb push_back
#define mp make_pair
#define fi first
#define se second
const int N = 1005;

int n,m;
char s[N][N];
int col[5] = {0,0,-1,1};
int con[5] = {-1,1,0,0};
bool vis[N][N];
int x2,y2;
vector<pair<int,int> >ve;
int dp[N][N];

bool judge(int i,int j)
{
    if(i < 0 || j < 0)
        return false;
    if(i >= n || j >= m)
        return false;
    return true;
}
//斜线递推
string bfs2()
{
    memset(dp,-1,sizeof(dp));
    string sx;
    int x,y;
    for(int i = 0;i < ve.size();++i){
        x = ve[i].fi;y = ve[i].se;
        dp[x][y] = s[x][y] - '0';
    }
    sx += '1';
    int x1,y1;
    for(int i = x + y + 1;i <= n + m - 2;++i){
        bool flag = false;
        for(int j = 0;j < n;++j){
            if(i - j >= 0 && i - j < m){
                x1 = j;y1 = i - j;
                //cout << x1 << " " << y1 << endl;
                if(x1 - 1 >= 0){
                    if(dp[x1 - 1][y1] != -1){
                        if(s[x1][y1] == '0') flag = true;
                        dp[x1][y1] = s[x1][y1] - '0';
                    }
                }
                if(y1 - 1 >= 0){
                    if(dp[x1][y1 - 1] != -1){
                        if(s[x1][y1] == '0') flag = true;
                        dp[x1][y1] = s[x1][y1] - '0';
                    }
                }
            }
        }
        //cout << "flag:" << " " << flag << endl;
        if(!flag){
            sx += '1';
        }else{
            sx += '0';
            for(int j = 0;j < n;++j){
                if(i - j >= 0 && i - j < m){
                    if(dp[j][i - j] == 1){
                        dp[j][i - j] = -1;
                    }
                }
            }
        }
    }
    return sx;
}
//先搜索一连串0后的第一个1的坐标
void bfs1()
{
    queue<pair<int,int> >que;
    que.push(mp(0,0));
    memset(vis,false,sizeof(vis));
    vis[0][0] = true;
    int ans = 0;
    while(!que.empty())
    {
        pair<int,int> tmp = que.front();
        que.pop();
        int x = tmp.fi,y = tmp.se;
        for(int i = 0;i < 4;++i){
            int x1 = x + col[i];
            int y1 = y + con[i];
            if(judge(x1,y1) && !vis[x1][y1]){
                vis[x1][y1] = true;
                if(s[x1][y1] == '0'){
                    if(x1 == n - 1 && y1 == m - 1){
                        ve.clear();
                        return ;
                    }
                    que.push(mp(x1,y1));
                }else{
                    //cout << x1 << " " << y1 << " " << ans << endl;
                    if(x1 + y1 > ans){
                        ve.clear();
                        ve.push_back(mp(x1,y1));
                        ans = x1 + y1;
                    }else if(x1 + y1 == ans){
                        ve.push_back(mp(x1,y1));
                    }
                }
            }
        }
    }
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        ve.clear();
        scanf("%d %d",&n,&m);
        for(int i = 0;i < n;++i){
            scanf("%s",s[i]);
        }
       
        if(s[0][0] == '1'){
            ve.pb(mp(0,0));
            string ans = bfs2();
            printf("%s\n",ans.c_str());
        }else{
            ve.clear();
            bfs1();
            //如果ve为0,说明最后一位是0
            if(ve.size() > 0){
                string ptr = bfs2();
                printf("%s\n",ptr.c_str());
            }else{
                printf("0\n");
            }
        }

    }
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值