HDU 5335 BFS

141 篇文章 0 订阅
13 篇文章 0 订阅

点击打开链接

题意:从左上角走到右下角的路径中要求所有数字组成的二进制最小

思路:考虑如果第一个元素不是1的话,该怎么办,因为要求前缀0不输出,那么我们找到所有的0可以走到的1,然后在处理,因为要这个二进制数最小,所以它的长度越短越好,那么对于所有0到达的第一个1,我们找到与终点的最近距离,然后将满足的全部放进容器中,如果第一个是1的话,也一样进去的只能是第一个元素,然后现在的元素到终点的距离相等,也就是说它们组成的数长度相同,那么怎么让它变小呢,就是如果当前步数可以走到0点,那么所有走到1点的全部不要了,这样走到最后的就是最小的了,具体看代码好理解些

#include <queue>
#include <vector>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3fll;
const int maxn=1010;
int n,m,num[maxn][2],dir[4][2]={{1,0},{0,1},{-1,0},{0,-1}},ans[maxn];
bool vis[maxn][maxn],vis1[maxn][maxn];
char str[maxn][maxn];
struct pos{
    int x,y;
    pos(int a,int b){x=a;y=b;}
};
vector<pos>G;
vector<pos>G1;
vector<pos>G2;
struct edge{
    int x,y;
};
void bfs(){
    queue<edge>que;
    edge c,ne;
    for(int i=0;i<n;i++)
        for(int j=0;j<m;j++)
            vis[i][j]=0;
    c.x=0,c.y=0;
    vis[c.x][c.y]=1;
    que.push(c);
    while(!que.empty()){
        c=que.front();que.pop();
        for(int i=0;i<4;i++){
            int xx=c.x+dir[i][0];
            int yy=c.y+dir[i][1];
            if(xx<0||xx>n-1||yy<0||yy>m-1||vis[xx][yy]) continue;
            if(str[xx][yy]=='1'){
                vis[xx][yy]=1;continue;
            }
            vis[xx][yy]=1;
            ne.x=xx;ne.y=yy;
            que.push(ne);
        }
    }
}
void rbfs(int len){
    int k=1;ans[0]=1;
    while(k<=len){
        G1.clear();G2.clear();
        int lll=G.size();
        for(int i=0;i<lll;i++){
            pos pp=G[i];
            for(int j=0;j<2;j++){
                int xx=pp.x+dir[j][0];
                int yy=pp.y+dir[j][1];
                if(xx<0||xx>n-1||yy<0||yy>m-1||vis1[xx][yy]) continue;
                if(str[xx][yy]=='0') G1.push_back(pos(xx,yy));
                else if(str[xx][yy]=='1') G2.push_back(pos(xx,yy));
                vis1[xx][yy]=1;
            }
        }
        if(G1.size()!=0) G=G1,ans[k++]=0;
        else G=G2,ans[k++]=1;
    }
}
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);G.clear();G1.clear();G2.clear();
        memset(vis1,0,sizeof(vis1));
        for(int i=0;i<n;i++) scanf("%s",str[i]);
        int k=0,min1=inf;
        if(str[0][0]=='1'){
            num[0][0]=0;num[0][1]=0;k=1;min1=n+m-2;
        }
        else{
            bfs();
            if(vis[n-1][m-1]){
                if(str[n-1][m-1]=='1') printf("1\n");
                else printf("0\n");
                continue;
            }
            for(int i=0;i<n;i++){
                for(int j=0;j<m;j++){
                    if(vis[i][j]&&str[i][j]=='1'){
                        num[k][0]=i,num[k++][1]=j;
                        min1=min(min1,(n-i-1)+(m-j-1));
                    }
                }
            }
        }
        for(int i=0;i<k;i++){
            int t=n-num[i][0]+(m-num[i][1])-2;
            if(t==min1) G.push_back(pos(num[i][0],num[i][1]));
        }
        rbfs(min1);
        for(int i=0;i<=min1;i++) printf("%d",ans[i]);
        printf("\n");
    }
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值