zoukankan      html  css  js  c++  java
  • 水池数目

     

    水池数目(YES)
    时间限制:3000 ms  |  内存限制:65535 KB
    难度:4

       
    描述
        南阳理工学院校园里有一些小河和一些湖泊,现在,我们把它们通一看成水池,假设有一张我们学校的某处的地图,这个地图上仅标识了此处是否是水池,现在,你的任务来了,请用计算机算出该地图中共有几个水池。

    输入
        第一行输入一个整数N,表示共有N组测试数据
        每一组数据都是先输入该地图的行数m(0<m<100)与列数n(0<n<100),然后,输入接下来的m行每行输入n个数,表示此处有水还是没水(1表示此处是水池,0表示此处是地面)
    输出
        输出该地图中水池的个数。
        要注意,每个水池的旁边(上下左右四个位置)如果还是水池的话的话,它们可以看做是同一个水池。
    样例输入

        2
        3 4
        1 0 0 0
        0 0 1 1
        1 1 1 0
        5 5
        1 1 1 1 0
        0 0 1 0 1
        0 0 0 0 0
        1 1 1 0 0
        0 0 1 1 1

    样例输出

        2
        3
           分析:首先可将所有map[i][j]为1的结点入队,然后再队非空时,每出一个结点,做是否visited的判断,对于未visited的结点,水池数+1,同时dfs将所有连通水池标记为visited

    #include <iostream>
    #include <cstdio> 
    #include <queue>
    #include <cstring>
    
    typedef struct node{
    	int x,y;
    }Node;
     
    using namespace std;
    
    queue <Node> q;
    int map[100][100];
    bool vis[100][100];
    int m,n,res;
    const int dir[][2]={-1,0,1,0,0,1,0,-1};
    
    void Input(){
    	int i,j;
    	Node p;
    	for(i=0;i<m;i++)
    		for(j=0;j<n;j++){
    			scanf("%d",&map[i][j]);
    			if(map[i][j]){
    				p.x=i,p.y=j;
    				q.push(p);
    			}
    		}
    }
    
    void DFS(Node p){
    	if(p.x<0 || p.x>=m || p.y<0 || p.y>=n)
    		return;
    	if(vis[p.x][p.y] || map[p.x][p.y]==0) 
    		return;
    	vis[p.x][p.y]=true;
    	int i;Node q;
    	for(i=0;i<4;i++){
    		q.x=p.x+dir[i][0];
    		q.y=p.y+dir[i][1];
    		DFS(q);
    	}
    }
    
    int main(){
    	int t;Node p;
    	scanf("%d",&t);
    	while(t--){
    		scanf("%d%d",&m,&n);
    		memset(vis,0,sizeof(vis));
    		res=0;
    		Input();
    		while(!q.empty()){
    			p=q.front(),q.pop();
    			if(!vis[p.x][p.y]){ 
    				res++;
    				DFS(p);
    			}
    		}
    		printf("%d
    ",res);
    	}
    	return 0;
    }
    
    
    

    补充:如果我们在Input阶段,选择下标从1开始接收,那么我们可省去越界的判断(需要在接收前将map init为0),而在DFS阶段,我们实际也不需要队列和vis标记,

    因为map本身可充当标记,核心代码如下:

    for(i=1;i<=n;i++)
        for(j=1;j<=m;j++)
            if(map[i][j]){ 
    	    res++; 
    	    map[i][j]=0; 
    	    DFS(i,j); 
    	}
    

      当然,将DFS用非递归来改写(加一个辅助队列q),自然效率更高。

    ............................................................ACM_沈建华...............................................................................
    for(i=0;i<m;i++) 
        for(j=0;j<n;j++)
            if(map[i][j]==1){
    		    s=0,e=1;
    		    a=i,b=j;
    		    while(s<e){
    				for(k=0;k<4;k++){
    					x=a+dir[k][0],y=b+dir[k][1];
    					if(x>=0 && x<m && y>=0 && y<n && map[x][y]==1){
    					     q[e++]=x*cons+y;//cons为自定义的常量 
    					     map[x][y]=0;
    					}
    				}
    				a=q[++s]/cons;
    				b=q[s]%cons;
            }
    	    	res++;
         }
    

     

     
  • 相关阅读:
    周鸿祎笔录
    set multiset 集合实现众数的统计
    栈实现 汉诺塔 操作是否符合规范
    优先队列----解决排序问题
    字符串的应用(续一)
    优先队列 的实例(未完----待续)
    字符串的应用
    栈实现括号
    Jave垃圾回收算法
    Java 按代回收垃圾以及回收算法
  • 原文地址:https://www.cnblogs.com/emptyCoder/p/6534845.html
Copyright © 2011-2022 走看看