HDU 1198 Farm Irrigation

传送门

这个题就是考建图,其实想起来以前玩的一个手机游戏就是这种类似铺管道的。
在矩阵里,每个点往4个方向看一下能不能和相邻点接上,但是这样的话要判断重复。更好的想法是往右下两个方向就行了,遍历矩阵按照外层从上到下,内层从左到右。

#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>
using namespace std;

const int MAXN = 50 + 2;
int M, N;
char mtx[MAXN][MAXN];

int x[4] = { -1,0,1,0 }; //  上左下右
int y[4] = { 0,-1,0,1 };
bool u[11] = { 0 };
bool l[11] = { 0 };      // left和right不能用
bool d[11] = { 0 };
bool r[11] = { 0 };

//bool vis[MAXN][MAXN][4];
int pre[MAXN*MAXN];
int conn;

struct edge
{
    int n1, n2;
};
vector<edge> v;

void create_map()
{
    for (int i = 0; i < M; i++)
    {
        for (int j = 0; j < N; j++) 
        {
            char t0 = mtx[i][j];
            for (int k = 2; k < 4; k++) // 从0,0 开始,其实只用向右下两个方向跑就行,不用担心边重复加了,也就不用vis了
            {
                int ni = i + x[k];
                int nj = j + y[k];
                if (ni < M && ni >= 0 && nj < N && nj >= 0 /*&& !vis[i][j][k]*/)
                {
                    char t = mtx[ni][nj];
                    if (/*k == 0 && u[t0 - 'A'] && d[t - 'A'] || k == 1 && l[t0 - 'A'] && r[t - 'a'] ||*/ k == 2 && d[t0 - 'A'] && u[t - 'A'] || k == 3 && r[t0 - 'A'] && l[t - 'A'])
                        v.push_back({ i*N + j,ni*N + nj });
                    //vis[ni][nj][k ^ 2] = 1;  // 异或2 就是 取反 低位第2位
                }
            }
        }
    }
}

void init()
{
    u[0] = 1;l[0] = 1;
    u[1] = 1;r[1] = 1;
    l[2] = 1;d[2] = 1;
    r[3] = 1;d[3] = 1;
    u[4] = 1;d[4] = 1;
    l[5] = 1;r[5] = 1;
    u[6] = 1;l[6] = 1;r[6] = 1;
    u[7] = 1;d[7] = 1;l[7] = 1;
    l[8] = 1;r[8] = 1;d[8] = 1;
    u[9] = 1;d[9] = 1;r[9] = 1;
    u[10] = 1;l[10] = 1;d[10] = 1;r[10] = 1;
}

int f(int n)
{
    int f0 = n, f1 = n;
    for (; pre[f0] >= 0;)
    {
        f0 = pre[f0];
    }
    for (; pre[f1] >= 0;)
    {
        int t = f1;
        f1 = pre[f1];
        pre[t] = f0;
    }
    return f0;
}

void un(int n1, int n2)
{
    int f1 = f(n1);
    int f2 = f(n2);
    if (f1 != f2)
    {
        conn++;
        if (pre[f1] <= pre[f2])
        {
            pre[f1] += pre[f2];
            pre[f2] = f1;
        }
        else
        {
            pre[f2] += pre[f1];
            pre[f1] = f2;
        }
    }
}

int main()
{
    init();
    for (; ~scanf("%d%d", &M, &N);)
    {
        if (M == -1 || N == -1) break;
        memset(pre, -1, sizeof pre);
        //memset(vis, 0, sizeof vis);
        conn = 0;
        v.clear();
        for (int i = 0; i < M; i++)
        {
            getchar();  //
            for (int j = 0; j < N; j++)
                scanf("%c", &mtx[i][j]);
        }
        create_map();
        for (int i = 0; i < v.size(); i++)
        {
            if (conn == M*N - 1) break;
            un(v[i].n1, v[i].n2);
        }
        // 删调试信息
        printf("%d\n", M*N - conn);
    }

    return 0;
}
posted @ 2017-04-08 18:04  CrossingOver  阅读(121)  评论(0编辑  收藏  举报