题目:http://acm.hdu.edu.cn/showproblem.php?pid=5335
题意:给你N*M的01矩阵,求从(1,1)位置走到(N,M)的最小二进制数,输出不含前导0。
分析:为了不让当前位置向上走,可以先将所有的起点预处理出来。当(1,1)为1,那么起点只有一个,就是(1,1);当(1,1)为0,起点就是从(1,1)可达的并且只走0的这些点,然后把这些起点离终点最近的所有点选出来,那么这些起点在一条斜线上,而且只能向右或者向下走。然后在斜线上递推,有0可走就只走0,否则走1。(也可以bfs搜,不过我写得有问题)
代码:
#pragma comment(linker, "/STACK:102400000,102400000") #include <iostream> #include <cstdio> #include <cstring> #include <vector> using namespace std; const int maxn = 1006; char str[maxn][maxn]; bool visit[maxn][maxn]; int ans[maxn*maxn+10],len,M,N; struct node { int x,y; node(int a=0,int b=0) :x(a),y(b){} }; vector <node > vct; void Init() { vct.clear(); for(int i=0;i<=N;i++) for(int j=0;j<=M;j++) { str[i][j]='#'; visit[i][j]=false; } } void DFS(int x,int y) { if( x>=1 && x<=N && y>=1 && y<=M && str[x][y]=='0' && !visit[x][y]) { vct.push_back(node(x,y)); visit[x][y]=true; DFS(x,y+1); DFS(x,y-1); DFS(x+1,y); DFS(x-1,y); } } void solve() { for(int i=0;i<=N;i++) for(int j=0;j<=M;j++) visit[i][j]=false; int Max=0; for(int i=0;i<vct.size();i++) if(vct[i].x+vct[i].y>Max) Max=vct[i].x+vct[i].y; for(int i=0;i<vct.size();i++) if(vct[i].x+vct[i].y==Max) visit[vct[i].x][vct[i].y]=true; int i,j,k,p,q; for(i=1;i<=N+M+1 && i+1<Max;i++) ; if(Max==0) { i=1; visit[1][1]=true; } for(;i<=N+M-1;i++) { if(i>=N+1) { j=N; k=i-N+1; } else { j=i; k=1; } bool fg=false; for(p=j,q=k;p>=1 && q<=M;p--,q++) { if(str[p][q]=='0' && visit[p][q]) { fg=true; break; } } if(fg) { ans[len++]=0; for(p=j,q=k;p>=1 && q<=M;p--,q++) { if(str[p][q]=='0' && visit[p][q]) { visit[p+1][q]=true; visit[p][q+1]=true; } } } else { ans[len++]=1; for(p=j,q=k;p>=1 && q<=M;p--,q++) { if(visit[p][q]) { visit[p+1][q]=true; visit[p][q+1]=true; } } } } } int main() { int ncase,i,j; scanf("%d",&ncase); while(ncase--) { scanf("%d%d",&N,&M); Init(); for(i=1;i<=N;i++) scanf("%s",str[i]+1); DFS(1,1); len=0; solve(); for(i=0;i<len && !ans[i] ;i++) ; if(i==len) printf("0\n"); else { for(;i<len;i++) printf("%d",ans[i]); printf("\n"); } } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-22 16:44:35