2 2 2 11 11 3 3 001 111 101
111 101
题意:要求从(0,0)走到(n-1 , m-1)经过的位置里的值组合成二进制数值最小。
解题:先用BFS从(0,0)出发,去掉前导0,找出离(n-1 , m-1 )最近的一些位置为1,然后再从找出的这些位置开始出发(每个位置只走一次),用两个数组模似两个队列,交换使用,每次队列里面的位置值要么全为0,要么全为1,这样即保证了最短长度,而且也保证了字典序最小。
5
15 15
101010111011010
110011011000111
100011110100100
101101100110011
100011000110011
100111111111001
101001101001100
100101001100110
100111111000010
101001001000110
101100100110100
100100110010010
110100100100110
100010010010001
111111111001001
10100000000000000100100001001
#include<stdio.h> #include<queue> #include<iostream> #include<string.h> #include<string> using namespace std; const int N = 1015; char mapt[N*N]; int fath[N*N],vist[N*N],dir[4][2]={1,0,0,1,0,-1,-1,0}; int n,m; int inq[2],q[2][N*N] , tq[N*N] , minlen; int ABS(int aa){return aa>0?aa:-aa;} void bfs1(int st) { int x,y,kk=0; memset(vist,0,sizeof(vist)); inq[0]=inq[1]=0; minlen=ABS(n-1-st/m)+ABS(m-1-st%m);//找一个位置为1的离(n-1,m-1)位置最近的一些点 if(mapt[st]=='0') tq[kk++]=st; vist[st]=1; while(kk) { st=tq[--kk]; x=st/m; y=st%m; for(int e=0; e<4; e++) { int tx=x+dir[e][0] , ty=y+dir[e][1]; if(tx>=0&&tx<n&&ty>=0&&ty<m&&vist[tx*m+ty]==0) { if(mapt[tx*m+ty]=='0') tq[kk++]=tx*m+ty; else { int tlen=ABS(n-1-tx)+ABS(m-1-ty); if(minlen>tlen)minlen=tlen; } vist[tx*m+ty]=1; } } } for(int i=0; i<n; i++) for(int j=0; j<m; j++) if(vist[i*m+j]==1&&mapt[i*m+j]=='1'&&ABS(n-1-i)+ABS(m-1-j)==minlen) { q[0][inq[0]++]=i*m+j; } } void bfs2(int endd) { int x,y,st,flag=0; memset(fath,-1,sizeof(fath)); //两个队列交换使用保证序列的长度一样 while(inq[flag]) { bool bb=0; //队列里的位置所在的格子值要么全是0,要么全1,这要才能保证字典序最小 for(int i=0; i<inq[flag]; i++) { st=q[flag][i]; x=st/m; y=st%m; for(int e=0; e<2; e++)//走两个方向:向右向下 { int tx=x+dir[e][0] , ty=y+dir[e][1] ; int tst=tx*m+ty; if(tx>=0&&tx<n&&ty>=0&&ty<m) if(mapt[tst]=='0'&&vist[tst]==0)//先找0 { fath[tst]=st; vist[tst]=1+vist[st]; if(tst==endd) { return ; } q[!flag][inq[!flag]++]=tst; bb=1; } } } if(bb==0) for(int i=0; i<inq[flag]; i++) { st=q[flag][i]; x=st/m; y=st%m; for(int e=0; e<2; e++) { int tx=x+dir[e][0] , ty=y+dir[e][1] ; int tst=tx*m+ty; if(tx>=0&&tx<n&&ty>=0&&ty<m) if(mapt[tst]=='1'&&vist[tst]==0) { fath[tst]=st; vist[tst]=1+vist[st]; if(tst==endd) { return ; } q[!flag][inq[!flag]++]=tst; } } } inq[flag]=0; flag=!flag; } } char str[N*N]; void prin(int endd) { int k=0; while(endd!=-1) { //printf("<-(%d,%d)%c ",endd/m,endd%m,mapt[endd]); str[k++]=mapt[endd]; endd=fath[endd]; } while(k--) { printf("%c",str[k]); } printf("\n"); } int main() { int T; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); for(int i=0; i<n; i++) { scanf("%s",str); for(int j=0; j<m; j++) mapt[i*m+j]=str[j]; } int endd=n*m-1; bfs1(0); if(vist[endd]!=0) { printf("%c\n",mapt[endd]); } else { bfs2(endd); prin(endd); } } }