zoukankan      html  css  js  c++  java
  • hdu5335(bfs,贪心)

    In an nmn∗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
    ",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
    ",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
    ",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
    ",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
    ",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
    ",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
    "); 
    			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
    ",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("
    ");
    		}
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    两种数组,注意用法
    PD 导出数据库结构
    获取随机金额:上限下限都要取到
    mysql常用语句
    SQL替换字符串、条件查询
    jtopo树结构方法积累
    jtopo 学习
    .net C# SortedList用法
    .net C# List用法
    .Net中C# Dictionary 用法(转)
  • 原文地址:https://www.cnblogs.com/cglongge/p/9359416.html
Copyright © 2011-2022 走看看