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