1. 程式人生 > >hdu5335(bfs,貪心)

hdu5335(bfs,貪心)

frame 有一個 swe wal std to do set lns printf

In an n?mn?m maze, the right-bottom corner is the exit (position (n,m)(n,m) is the exit). In every position of this maze, there is either a 00 or a 11 written on it.

An explorer gets lost in this grid. His position now is (1,1)(1,1), and he wants to go to the exit. Since to arrive at the exit is easy for him, he wants to do something more difficult. At first, he‘ll write down the number on position
(1,1)(1,1). Every time, he could make a move to one adjacent position (two positions are adjacent if and only if they share an edge). While walking, he will write down the number on the position he‘s on to the end of his number. When finished, he will get a binary number. Please determine the minimum value of this number in binary system.

InputThe first line of the input is a single integer T (T=10)T (T=10), indicating the number of testcases.

For each testcase, the first line contains two integers nn and m (1n,m1000)m (1≤n,m≤1000). The ii-th line of the next nn lines contains one 01 string of length mm, which represents ii-th row of the maze.

OutputFor each testcase, print the answer in binary system. Please eliminate all the preceding 00 unless the answer itself is 00 (in this case, print 00 instead).Sample Input

2
2 2
11
11
3 3
001
111
101

Sample Output

111
101
題意:給出t組數據,每組數據給出一個n*m的圖,圖中每一個位置都有一個數字(0或1),每走到一個位置都會記錄當前位置上的數字,要你求從左上角走到右下角中組成的最小的二進制數。
思路:當當前還沒有1的時候,我們就可以先找出距離(距離=n+m-i-j+1)右下角最近的位置的0(位置可能不止一個)(到這個位置走的路上的數字都要求是0),然後我們就可以保證它的位數最小,為了保持位數
的最小,我們只能向右或向下走,每次走的時候,把這些位置都壓入一個隊列,然後進行bfs,每走到一個位置,我們都判斷一下當前和這個位置到右下角距離相同的位置上是否有0,有零則非零的位置就可以不必往
後走了,用一個數組記錄下每個位置都由那個方向走過來的,最後從右下角進行回溯記錄答案就可以了。
代碼:
#include<cstdio> 
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
char mp[1010][1010];
int mv[2][4]={1,0,0,-1,0,1,-1,0};
int vt[1010][1010];
int mt[1010][1010];
int vz[3030];
int lg;
int n,m;
char ans[1010];
struct st{
	int x,y;
};
vector<st> v;
queue<st> q;
int check(int x,int y){
	if(x<=n&&x>0&&y<=m&&y>0)
	return 1;
	return 0;
}
int bfs(){//找最近的1 
	int i,j;
	st a,b;
	memset(vt,0,sizeof(vt));//一定要記得清零 
	v.clear();//清空數組 
	a.x=1;
	a.y=1;
	int dis=1;
	q.push(a);	
	vt[a.x][a.y]=1;
	v.push_back(a);
	int c;
	while(!q.empty()){
		a=q.front();
		q.pop();	
		for(i=0;i<4;i++){
			b.x=a.x+mv[0][i];
			b.y=a.y+mv[1][i];			
			//printf("%d %d %d\n",mp[b.x][b.y]==‘0‘,!vt[b.x][b.y],check(b.x,b.y));	
			if(mp[b.x][b.y]==‘0‘&&!vt[b.x][b.y]&&check(b.x,b.y)){
				c=b.x+b.y-1;
				//printf("b%d %d %d\n",b.x,b.y,c);
				q.push(b);//把所有的可能的未標記的位置壓入隊列 
				if(c>dis){// 找到了新的最遠距離 
					v.clear();//清空之前放入的位置 
					v.push_back(b);
					dis=c;
				}
				else if(c==dis){
					v.push_back(b);
					
				}
				vt[b.x][b.y]=1;//標記 
			}
		}
	}
	//printf("Q%d\n",dis);
	return dis;//返回最遠距離 
}
/*3 
5 6
001000 
101010
101010
100010
111111
3 3
111
101
111
3 3
001
010
100
3 3
101
010
101*/ 
int bfs1(){
	int i,j;
	st a,b;
	memset(vt,0,sizeof(vt));//一定要全部清零 
	memset(vz,0,sizeof(vz));
	memset(mt,0,sizeof(mt));
	vt[1][1]=1;
	for(i=0;i<v.size()&&mp[1][1]==‘0‘;i++){
		q.push(v[i]);//放入找出的最遠的位置 
		//printf("v%d %d\n",v[i].x,v[i].y);
		vt[v[i].x][v[i].y]=1;
	}
	while(!q.empty()){
		a=q.front();
		//printf("a%d %d %d\n",a.x,a.y,vt[n][m]);
		q.pop();
		if(mp[a.x][a.y]==‘1‘&&vz[a.x+a.y-1])//如果和這個位置相同遠的位置有0並且當前位置非零,這條路就一定不是最小的 ,就不必走下去了 
		continue;
		for(i=0;i<2;i++){//向下和向右走 
			b.x=a.x+mv[0][i];
			b.y=a.y+mv[1][i];		
			if(!vt[b.x][b.y]&&check(b.x,b.y)){		
				mt[b.x][b.y]=3-i;//記錄該位置是由哪個方向走來的,便於回溯 
				//printf("b%d %d %d\n",b.x,b.y,3-i);
				if(mp[b.x][b.y]==‘0‘)//當前位置為0 
				vz[b.x+b.y-1]=1;
				q.push(b);//放入隊列 
				vt[b.x][b.y]=1;//標記 
			}
		}
	}
}
int main(){
	int t;
	int i,j;
	int lg=0,cnt;
	scanf("%d",&t);
	while(t--){
		lg=0;
		scanf("%d%d",&n,&m);
		for(i=1;i<=n;i++){
			getchar();
			scanf("%s",mp[i]+1);
		}
		lg=0;
		st a;
		a.x=1;
		a.y=1;
		if(mp[1][1]==‘0‘&&bfs()==(n+m-1)){//看是否有一條全為0的路 
			printf("0\n"); 
			lg=1;
		}	
		else if(!lg){
			if(mp[1][1]==‘1‘){
				q.push(a);
				v.clear();//清空上一組數據的最遠位置 
			}
			bfs1();
			int x,y,t;
			x=n,y=m;
			t=mt[x][y];//回溯方向 
			//printf("t%d\n",t);
			cnt=0;
			while(t>1){
				ans[cnt++]=mp[x][y];
				x+=mv[0][t];
				y+=mv[1][t];
				t=mt[x][y];
			}
			while(ans[cnt-1]==‘0‘&&cnt>1&&mp[1][1]==‘0‘)//清除前綴零 
			cnt--;
			if(mp[1][1]==‘1‘)//第一個位置沒有來自的位置 
			printf("1");
			for(i=cnt-1;i>=0;i--)//逆向輸出答案 
			printf("%c",ans[i]);
			printf("\n");
		}
	}
	return 0;
}

  

hdu5335(bfs,貪心)