hdu5335 已知起点终点 找最小的01串

wa了27次,终于过了

先找到通过0可以到达的最远的1的位置,答案的长度就固定了,然后对每个斜对角线进行扫描,有0就走0,否则走1

#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include<stdio.h>
#include<string.h>
#include<vector>
#include<algorithm>
#include<cmath>
#include<map>
#include<queue>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1 | 1
using namespace std;
const int N=1e3+10;
int INF=0x7f7f7f7;
int T,n,m,k;
int tot[2];
const int MOD=1e9+7;
char a[N][N];
char str[N*N];
struct node{
    int x,y;
};
node vec[N*N];
int num;
node q[N*N] ;
node ans[2][N];
int now;
bool vis[N][N];
bool ok;
int cnt;
int dir[]={0,1,0,-1,1,0,-1,0};
void bfs(){
      memset(vis,0,sizeof vis);
      num=0;
      int l=0,r=0;
      cnt=0;
      q[r++]=node{1,1};
      vis[1][1]=true;
      while(l<r){
         node tmp=q[l++];
         int x=tmp.x,y=tmp.y;
         if(x==n && y==m){
            ok=true;
         }
         if(a[x][y]=='1'){
            if(x+y>cnt){
                cnt=x+y;
                num=0;
                vec[num++]=tmp;/*保存通过0走到的最远的1的位置*/
            }else if(x+y==cnt){
                vec[num++]=tmp;
            }
            continue;
         }
         for(int i=0;i<8;){
            int dx=x+dir[i++];
            int dy=y+dir[i++];
            if(dx<1 || dx>n || dy<1 || dy>m || vis[dx][dy]) continue;
            q[r++]=node{dx,dy};
            vis[dx][dy]=true;
         }
      }
}
void solve(){
    if(num==0){
        puts("0");
        return;
    }
    int len=n+m-cnt+1;/*答案的长度是已知的*/
    str[0]='1';
    str[len]='\0';
    int step=0;
   memset(vis,0,sizeof vis);
    for(int i=0;i<len-1;i++){/*斜对角线扫描*/

        tot[0]=tot[1]=0;/*保存下一个斜线中0和1的个数*/
        for(int j=0;j<num;j++){
            node u=vec[j];
            int x=u.x,y=u.y;
            if(x+1<=n && !vis[x+1][y]){
                 vis[x+1][y]=true;
                if(a[x+1][y]=='0') ans[0][tot[0]++]=node{x+1,y};
                else ans[1][tot[1]++]=node{x+1,y};
            }
            if(y+1<=m && !vis[x][y+1]){
                vis[x][y+1]=true;
                if(a[x][y+1]=='0') ans[0][tot[0]++]=node{x,y+1};
                else ans[1][tot[1]++]=node{x,y+1};
            }

        }

        if(tot[0]){ /*有0 一定是走0的位置*/
            str[++step]='0';
            num=tot[0];
            for(int j=0;j<tot[0];j++) vec[j]=ans[0][j];
        }else{ /*否则就走1*/
            str[++step]='1';
            num=tot[1];
            for(int j=0;j<tot[1];j++) vec[j]=ans[1][j];
        }
    }
    printf("%s\n",str);
}
int main()
{
#ifndef  ONLINE_JUDGE
 freopen("aaa","r",stdin);
#endif
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        scanf("%s",a[i]+1);
        ok=false;
        bfs();
        if(ok) printf("%c\n",a[n][m]); /*如果可以通过0走到终点,就输出最后的一个字符*/
       else solve();

    }

    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值