标签:
题意:给出一幅图,起点在左上角终点在左下角。沿途走过的数字连起来为最后所得的二进制数,设法令该数最小,输出之。
思路:
起点为1的情况,令二进制数长度最小,则每次只往右走或往下走,并且步数相同时走 0 优先。
起点为0的情况,则按着 0 搜到离终点最近的为 1 的点,再按上述的方式走即可。
广搜题,,但 T 到跪。看了标程打了一份。这种 bfs 方式第一次见,确实6,我还是太年轻。。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<string> using namespace std; char g[1005][1005]; int n,m,t,head,tail; #define maxn 1000005 int vis[1005][1005],x[maxn],y[maxn]; int dx[]={1,-1,0,0},dy[]={0,0,1,-1}; string bfs(){ memset(vis,0,sizeof(vis)); vis[head=0][tail=0]=1; x[head]=0,y[head++]=0; while(head!=tail){ if(g[x[tail]][y[tail]]==‘0‘){ for(int i=0;i<4;i++){ int X=x[tail]+dx[i],Y=y[tail]+dy[i]; if(X>=0&&X<n&&Y>=0&&Y<m&&!vis[X][Y]){ x[head]=X,y[head++]=Y; vis[X][Y]=1; } } } tail++; } if(vis[n-1][m-1]&&g[n-1][m-1]==‘0‘) return "0"; int sum=0; string ans="1"; for(int i=0;i<n;i++){ for(int j=0;j<m;j++) if(vis[i][j]) sum=max(sum,i+j); } for(int k=sum;k<n+m-2;k++){ char c=‘1‘; for(int i=0,j=k-i;i<n;i++,j--) if(j>=0&&j<m&&vis[i][j]){ if(i+1<n) c=min(c,g[i+1][j]); if(j+1<m) c=min(c,g[i][j+1]); } ans+=c; for(int i=0,j=k-i;i<n;i++,j--) if(j>=0&&j<m&&vis[i][j]){ if(i+1<n&&g[i+1][j]==c) vis[i+1][j]=1; if(j+1<m&&g[i][j+1]==c) vis[i][j+1]=1; } } return ans; } int main(){ //freopen("in.txt","r",stdin); scanf("%d",&t); while(t--){ scanf("%d%d",&n,&m); for(int i=0;i<n;i++) scanf("%s",g[i]); cout<<bfs()<<endl; } return 0; }
标签:
原文地址:http://www.cnblogs.com/names-yc/p/4703099.html