这道题目主要是构图,之后就是水水地求连通分量个数了,用广搜,用深搜,用并查集都行,不过并查集效率要高。

/*
*State: HDU1198 46MS 372K 2322 B C++ 
*题目大意:
*        给定A~K个固定的小方块,方块中有水管,然后要求凑这些小方块成为
*        一个大矩形,求最后形成的连通分量数目。
*解题思路:
*        主要是构图比较特别。枚举每个小方块构图,最后用dfs查连通分量数即可。
*        图可构为无向图。
*解题感想:
*        好像用map慢了许多。第三次优化用了并查集,果然0ms了,连建图都省了
*/

并查集版本:

View Code
//第三次优化
//State:  HDU1198 0MS 264K 2185 B C++
//果然求无向图连通分量数,用并查集要快很多
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

const int MAXN = 2505;
typedef struct _node
{
    int up, down, left, right;
    _node():up(0), down(0), left(0), right(0) {};
}N;

typedef struct _Set
{
    int parent;
}Set;

Set mySet[MAXN];
N sq[11];
char Map[51][51];
int dir[4][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};

void init()
{
    for(int i = 0; i < MAXN; i++)
        mySet[i].parent = i;

    sq[0].up = sq[0].left = 1;
    sq[1].up = sq[1].right = 1;
    sq[2].left = sq[2].down = 1;
    sq[3].down = sq[3].right = 1;
    sq[4].up = sq[4].down = 1;
    sq[5].left = sq[5].right = 1;
    sq[6].left = sq[6].up = sq[6].right = 1;
    sq[7].left = sq[7].up = sq[7].down = 1;
    sq[8].left = sq[8].down = sq[8].right = 1;
    sq[9].up = sq[9].right = sq[9].down = 1;
    sq[10].left = sq[10].up = sq[10].right = sq[10].down = 1;
}

int findSet(int x)
{
    if(x != mySet[x].parent)
        mySet[x].parent = findSet(mySet[x].parent);
    return mySet[x].parent;
}

void Union(int x, int y)
{
    x = findSet(x);
    y = findSet(y);
    if(x == y)
        return ;
    else
        mySet[y].parent = x;
}

void bulid(int n, int m)
{
    int ni, nj;
    for(int i = 0; i < n; i++)
        for(int j = 0; j < m; j++)
        {
            for(int k = 0; k < 4; k++)
            {
                ni = i + dir[k][0];
                nj = j + dir[k][1];
                if(ni >= 0 && ni < n && nj >= 0 && nj < m)
                {
                    int u = i * m + j;
                    int v = ni * m + nj;

                    int ind = Map[i][j] - 'A';
                    int other = Map[ni][nj] - 'A';

                    if(sq[ind].up && sq[other].down && k == 0)
                        Union(u, v);
                    if(sq[ind].right && sq[other].left && k == 1)
                        Union(u, v);
                    if(sq[ind].down && sq[other].up && k == 2)
                        Union(u, v);
                    if(sq[ind].left && sq[other].right && k == 3)
                        Union(u, v);
                }
            }
        }
}

int main(void)
{
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
#endif

    int n, m;
    while(scanf("%d %d", &n, &m), n > 0 && m > 0)
    {
        init();
        
        for(int i = 0; i < n; i++)
            scanf("%s", Map[i]);
        bulid(n, m);
        int tolN = n * m, ans = 0;
        for(int i = 0; i < tolN; i++)
        {
            if(mySet[i].parent == i)
                ans++;
        }
        printf("%d\n", ans);
    }
    return 0;
}

深搜版本:

View Code
  1 #include <iostream>
  2 #include <vector>
  3 #include <cstdio>
  4 #include <cstring>
  5 using namespace std;
  6 
  7 const int MAXN = 2505;
  8 typedef struct _node
  9 {
 10     int up, down, left, right;
 11     _node():up(0), down(0), left(0), right(0) {};
 12 }N;
 13 
 14 N sq[11];
 15 char Map[51][51];
 16 vector<int> vec[MAXN];
 17 int dir[4][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
 18 int vst[MAXN];
 19 
 20 void init()
 21 {
 22     memset(vst, 0, sizeof(vst));
 23     for(int i = 0; i < MAXN; i++)
 24         vec[i].clear();
 25 
 26     sq[0].up = sq[0].left = 1;
 27     sq[1].up = sq[1].right = 1;
 28     sq[2].left = sq[2].down = 1;
 29     sq[3].down = sq[3].right = 1;
 30     sq[4].up = sq[4].down = 1;
 31     sq[5].left = sq[5].right = 1;
 32     sq[6].left = sq[6].up = sq[6].right = 1;
 33     sq[7].left = sq[7].up = sq[7].down = 1;
 34     sq[8].left = sq[8].down = sq[8].right = 1;
 35     sq[9].up = sq[9].right = sq[9].down = 1;
 36     sq[10].left = sq[10].up = sq[10].right = sq[10].down = 1;
 37 }
 38 
 39 void addEdge(int u, int v)
 40 {
 41     vec[u].push_back(v);
 42     vec[v].push_back(u);
 43 }
 44 
 45 void bulid(int n, int m)
 46 {
 47     int ni, nj;
 48     for(int i = 0; i < n; i++)
 49         for(int j = 0; j < m; j++)
 50         {
 51             for(int k = 0; k < 4; k++)
 52             {
 53                 ni = i + dir[k][0];
 54                 nj = j + dir[k][1];
 55                 if(ni >= 0 && ni < n && nj >= 0 && nj < m)
 56                 {
 57                     int u = i * m + j;
 58                     int v = ni * m + nj;
 59 
 60                     int ind = Map[i][j] - 'A';
 61                     int other = Map[ni][nj] - 'A';
 62 
 63                     if(sq[ind].up && sq[other].down && k == 0)
 64                         addEdge(u, v);
 65                     if(sq[ind].right && sq[other].left && k == 1)
 66                         addEdge(u, v);
 67                     if(sq[ind].down && sq[other].up && k == 2)
 68                         addEdge(u, v);
 69                     if(sq[ind].left && sq[other].right && k == 3)
 70                         addEdge(u, v);
 71                 }
 72             }
 73         }
 74 }
 75 
 76 void dfs(int n)
 77 {
 78     vst[n] = 1;
 79     for(unsigned i = 0; i < vec[n].size(); i++)
 80     {
 81         int son = vec[n][i];
 82         if(!vst[son])
 83         {
 84             dfs(son);
 85         }
 86     }
 87 }
 88 
 89 int main(void)
 90 {
 91 #ifndef ONLINE_JUDGE
 92     freopen("in.txt", "r", stdin);
 93 #endif
 94 
 95     int n, m;
 96     while(scanf("%d %d", &n, &m), n > 0 && m > 0)
 97     {
 98         init();
 99         
100         for(int i = 0; i < n; i++)
101             scanf("%s", Map[i]);
102         bulid(n, m);
103         int tolN = n * m, ans = 0;
104         for(int i = 0; i < tolN; i++)
105         {
106             if(!vst[i])
107             {
108                 ans++;
109                 dfs(i);
110             }
111         }
112         printf("%d\n", ans);
113     }
114     return 0;
115 }
posted on 2012-08-16 01:20  cchun  阅读(223)  评论(0编辑  收藏  举报