HDU-1198-Farm Irrigation

题目传送门:http://acm.hdu.edu.cn/showproblem.php?pid=1198

 

 

程序分析:

  题意就是说有一块大田,分为很多小块的,其中每块田都有各种各样形状的水渠,现要灌溉整块大田,问需要多少个水源可以完成。给你那些小田的水渠形状图,最多有上下左右四个方向可以把水输出去。

解决方法:

  并查集思想,能合并的就合并为一块田,这样总能灌溉到了吧,哪么,能合并的条件是什么?对应方向可以把水渠对上去就可以合并。

  可以用矩阵来存储每一块田的位置编号和图的编号,

 

 

 

 

 

 

 

 

 

 

View Code
  1 #include<iostream>
  2 #include<string>
  3 using namespace std;
  4 
  5 const int Max = 55;
  6 int Far[Max*Max];
  7 int Rank[Max*Max];
  8 int Sign[Max*Max];
  9 int Map[Max][Max];
 10 int Flag[Max][Max];
 11 
 12 class Node
 13 {
 14 public:
 15     Node(int u, int d, int l, int r):up(u),down(d),left(l),right(r) 
 16     { }
 17     int up;    //
 18     int down;  //
 19     int left;  //
 20     int right; //
 21 };
 22 
 23 Node Farm[12] = {
 24     Node(0,0,0,0),  //
 25     Node(1,0,1,0),  //A
 26     Node(1,0,0,1),  //B
 27     Node(0,1,1,0),  //C
 28     Node(0,1,0,1),  //D
 29     Node(1,1,0,0),  //E
 30     Node(0,0,1,1),  //F
 31     Node(1,0,1,1),  //G
 32     Node(1,1,1,0),  //H
 33     Node(0,1,1,1),  //I
 34     Node(1,1,0,1),  //J
 35     Node(1,1,1,1)   //K
 36 };
 37 
 38 
 39 void Make_set(int n)
 40 {
 41     int i;
 42     for(i=0; i<=n*n; i++)
 43     {
 44         Far[i] = i;
 45     }
 46     memset(Rank, 0, sizeof(Rank));
 47     memset(Sign, 0, sizeof(Sign));
 48 }
 49 
 50 int Find_set(int x)
 51 {
 52     if(Far[x] != x)
 53         return Far[x] = Find_set(Far[x]);
 54     return Far[x];
 55 }
 56 
 57 void Unio(int a, int b)
 58 {
 59     a = Find_set(a);
 60     b = Find_set(b);
 61     if(a == b)
 62         return;
 63     if(Rank[a] < Rank[b])
 64         Far[a] = b;
 65     else if(Rank[a] > Rank[b])
 66         Far[b] = a;
 67     else 
 68     {
 69         Far[a] = b;
 70         Rank[b]++;
 71     }
 72 }
 73 
 74 int main()
 75 {
 76     int m, n;
 77     int k, up, left;
 78     while(cin>>m>>n && m!=-1 && n!=-1)
 79     {
 80         Make_set(Max);
 81         memset(Map, 0, sizeof(Max));
 82         string str;
 83         int ans = 1;
 84         for(int i=1; i<=m; i++)
 85         {
 86             cin>>str;
 87 
 88             //合并
 89             for(int j=1; j<=n; j++)
 90             {
 91                 Flag[i][j] = ans++;
 92                 k = str[j-1]-'A'+1;
 93                 up = Map[i-1][j];
 94                 left = Map[i][j-1];
 95                 Map[i][j] = k;
 96                 //只跟上面的和左边的比较,可以合并就把他们所在块的代表数字合并
 97                 if(Farm[up].down == 1 && Farm[k].up == 1)  
 98                     Unio(Flag[i-1][j], Flag[i][j]);
 99                 if(Farm[left].right == 1 && Farm[k].left == 1)
100                     Unio(Flag[i][j-1], Flag[i][j]);
101             }
102         }
103 
104         //统计
105         int count = 0;   //记录有多少块分开的田
106         for(int z=1; z<ans; z++)
107         {
108             if(Find_set(z) == z)
109                 count++;
110         }
111         cout<<count<<endl;
112     }
113     return 0;
114 }

 

posted @ 2012-08-25 21:47  另Ⅰ中Feel▂  阅读(141)  评论(0编辑  收藏  举报