1099 PIPI的油田(使用查并集)

1099 PIPI的油田

  • 描述: PIPI承包了一大片土地,PIPI打了几个油井,发现这片土地的下面有很多地方埋藏着石油,如果一个油井与另一个油井在上,下,左,右,左上,右下,右上,左下这八个方向中的任意一个方向连通,我们就认为这两个油井属于同一个油田。
    现在这块土地可以看成是一个n*m的方格矩阵,标记为’@‘的方格代表一个油井,标记为’*'的方格代表一块贫瘠的土地。你能告诉PIPI他的这块土地上有几个油田吗?

  • 输入:输入包含多组测试样例。
    对于每组测试样例,输入的第一行是两个正整数 n,m (1<=n,m<=100)
    接下来输入的一个n*m的方格矩阵,代表PIPI承包土地。
    以 0 0结尾结束输入。

  • 输出:对于每组测试样例,输出一行,代表土地上油田的数目。

  • 输入示例

    1 1
    *
    3 5
    *@*@*
    **@**
    *@*@*
    1 8
    @@****@*
    5 5 
    ****@
    *@@*@
    *@**@
    @@@*@
    @@**@
    0 0 
    
  • 输出示例

    0
    1
    2
    2
    
  • 代码块

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N = 100;
    
    int f[N*N];//并查集
    int getFather(int x){
        // if(x == f[x]) return x;
        // else{
        //     f[x] = GetFather(f[x]);//父节点设为根节点
        //     return f[x];//返回父节点
        // }
        return x==f[x]?x:f[x]=getFather(f[x]);//路径压缩
    }
    
    int dx[] = {1, 1, 1, -1, -1, -1, 0, 0};
    int dy[] = {0, -1, 1, 0, 1, -1, 1, -1};//方向数组
    
    char mp[N][N];//地图
    int main(){
        int i, j, n, m;
        while(~scanf(" %d %d", &n, &m)){
            if(n == 0 && m == 0) break;
            int cnt = n*m;
            for(i=0; i<n; i++){
                scanf("%s", mp[i]);
            }
            for(i=0; i<cnt; i++) f[i] = i;//初始化
            for(i=0; i<n; i++){
                for(j=0; j<m; j++){
                    if(mp[i][j] == '*'){
                        cnt--;//土地直接让连同分量减一
                    }else{
                        for(int k=0; k<8; k++){
                            int nx = i+dx[k];//新的横坐标
                            int ny = j+dy[k];
                            if(nx>=0 && nx<n && ny>=0 && ny<m && mp[nx][ny] == '@'){
                                int fx = getFather(i*m+j);
                                int fy = getFather(nx*m+ny);
                                if(fx != fy){
                                    cnt--;
                                    f[fx] = fy;//合并
                                }
    
                            }
                        }
                    }
                }
            }
            printf("%d\n", cnt);
        } 
    }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值