hdu 1198 Farm Irrigation

acm.hdu.edu.cn/showproblem.php?pid=1198

较为隐蔽的并查集题目,但是分析发现还是统计集合个数的问题,需要注意的是集合的合并是有条件的,满足条件的合并,不满足的不合并。

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>

using namespace std;

const int MAX = 500;
int n,m,cnt,father[MAX*MAX],hash[MAX][MAX];

int d[12][4] = {{1,0,0,1},{1,1,0,0},{0,0,1,1},{0,1,1,0},{1,0,1,0},
                {0,1,0,1},{1,1,0,1},{1,0,1,1},{0,1,1,1},{1,1,1,0},{1,1,1,1}};
//预处理每一块图案能连通的方向(上右下左)
 int Move[][2] = {{-1,0},{0,1},{1,0},{0,-1}};//方向数组
char map[MAX][MAX];

bool II(int x, int y){
    if(x < 0 || x >= n || y < 0 || y >= m)
        return false;
    return true;
}

void Init(){
    for(int i=0; i<=n*m; i++)
        father[i] = i;
}

int Find(int x){
    if(x != father[x])
        father[x] = Find(father[x]);
    return father[x];
}

void Union(int x, int y){
    int xx = Find(x), yy = Find(y);
    father[yy] = xx;
    return;
}

int main(){
    while(scanf("%d%d",&n,&m) == 2){
        if(n == -1 && m == -1) break;
        Init();
        for(int i=0; i<n; i++) cin >> map[i];
        for(int i=0; i<n; i++)
            for(int j=0; j<m; j++)
            	hash[i][j] = i*m+j;//哈希的思想给每个结点标号,标号必须不重复
        for(int i=0; i<n; i++){
            for(int j=0; j<m; j++){
                for(int k=0; k<4; k++){
                    int dx = i + Move[k][0], dy = j + Move[k][1];
                    if(!II(dx, dy)) continue;
                    int idu = map[i][j] - 'A', idv = map[dx][dy] - 'A';
                    if(k == 0 && d[idu][0] && d[idv][2]) Union(hash[i][j], hash[dx][dy]);
                    else if(k == 1 && d[idu][1] && d[idv][3]) Union(hash[i][j], hash[dx][dy]);
                    else if(k == 2 && d[idu][2] && d[idv][0]) Union(hash[i][j], hash[dx][dy]);
                    else if(k == 3 && d[idu][3] && d[idv][1]) Union(hash[i][j], hash[dx][dy]);
                }
            }
        }
        cnt = 0;
        for(int i=0; i<n; i++)
            for(int j=0; j<m; j++)
                if(father[i*m+j] == i*m+j) cnt++;
        printf("%d\n",cnt);
    }
    return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值