题意:从左上角走到右下角的路径中要求所有数字组成的二进制最小
思路:考虑如果第一个元素不是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;
}