HDU 1198:Farm Irrigation
来源:互联网 发布:虚拟机软件有哪些 知乎 编辑:程序博客网 时间:2024/05/27 06:52
Farm Irrigation
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 9714 Accepted Submission(s): 4253
Problem Description
Benny has a spacious farm land to irrigate. The farm land is a rectangle, and is divided into a lot of samll squares. Water pipes are placed in these squares. Different square has a different type of pipe. There are 11 types of pipes, which is marked from A to K, as Figure 1 shows.
Figure 1
Benny has a map of his farm, which is an array of marks denoting the distribution of water pipes over the whole farm. For example, if he has a map
ADC
FJK
IHE
then the water pipes are distributed like
Figure 2
Several wellsprings are found in the center of some squares, so water can flow along the pipes from one square to another. If water flow crosses one square, the whole farm land in this square is irrigated and will have a good harvest in autumn.
Now Benny wants to know at least how many wellsprings should be found to have the whole farm land irrigated. Can you help him?
Note: In the above example, at least 3 wellsprings are needed, as those red points in Figure 2 show.
Benny has a map of his farm, which is an array of marks denoting the distribution of water pipes over the whole farm. For example, if he has a map
ADC
FJK
IHE
then the water pipes are distributed like
Several wellsprings are found in the center of some squares, so water can flow along the pipes from one square to another. If water flow crosses one square, the whole farm land in this square is irrigated and will have a good harvest in autumn.
Now Benny wants to know at least how many wellsprings should be found to have the whole farm land irrigated. Can you help him?
Note: In the above example, at least 3 wellsprings are needed, as those red points in Figure 2 show.
Input
There are several test cases! In each test case, the first line contains 2 integers M and N, then M lines follow. In each of these lines, there are N characters, in the range of 'A' to 'K', denoting the type of water pipe over the corresponding square. A negative M or N denotes the end of input, else you can assume 1 <= M, N <= 50.
Output
For each test case, output in one line the least number of wellsprings needed.
Sample Input
2 2DKHF3 3ADCFJKIHE-1 -1
Sample Output
23
总共有11种田地。建立结构体,来记录田地下方下水管道的情况。up,down,left,right。如果该田地有朝上的管道up=1,否则up=0.如果该田地有朝下的管道,down=1.
否则down = 0.如果该田地有朝左的管道,left=1,否则left=0,如果该田地有朝右的管道,right=1,right=0.
首先要把这11种田地下管道的情况存起来。
那么这里给出两种思路:
1.搜索解法,和搜索入门题统计油田个数的方法一样。挨个遍历M*N块田地,如果某块田地没有标记过,则以该块田地开始进行深搜或广搜,能够搜到的田地都进行标记。
代表这些田地与(源田地)相通。水井个数加1.
2.如果两块田地有管道相同,那么他们从属于一个集合。因此可以用并查集来处理。如果第s块田地与第t块田地有管道相通,求s和t所属的集合,如果他们已经在同一集合中。
不进行操作,否则进行集合合并操作。
1.搜索解法:
#include <iostream>#include <stdio.h>#include <string.h>#include <string>#include <math.h>#include <queue>#include <stdlib.h>#define INF 0x3f3f3f3fusing namespace std;const int MAXN = 55;int Map[MAXN][MAXN];int M,N;int vis[MAXN][MAXN];int dir[4][2] = {{-1,0},{0,1},{1,0},{0,-1}}; ///搜索顺序上右下左struct node{ int up; ///上 int down; ///下 int left; ///左 int right; ///右}area[13];struct pos{ int x; int y;};void Init() ///将11种土地下的管道情形都先列出来。{ memset(area,0,sizeof(area)); area[0].up = 1; area[0].left = 1; area[1].up = 1; area[1].right = 1; area[2].left = 1; area[2].down = 1; area[3].down = 1; area[3].right = 1; area[4].up = 1; area[4].down = 1; area[5].left = 1; area[5].right = 1; area[6].up = 1; area[6].left = 1; area[6].right = 1; area[7].up = 1; area[7].left = 1; area[7].down = 1; area[8].left = 1; area[8].right = 1; area[8].down = 1; area[9].up = 1; area[9].down = 1; area[9].right = 1; area[10].up = 1; area[10].down = 1; area[10].left = 1; area[10].right = 1;}void bfs(int x,int y) ///广搜,也可以用深搜{ vis[x][y] = 1; pos now,nex; now.x = x; now.y = y; queue<pos>qu; qu.push(now); while(!qu.empty()) { now = qu.front(); qu.pop(); for(int i = 0; i < 4; i++) { int temp = Map[now.x][now.y]; ///这个位置上的田地是哪一种田地 nex.x = now.x + dir[i][0]; nex.y = now.y + dir[i][1]; ///下一个点没有越界,而且没有访问过 if(nex.x>=0&&nex.x<M&&nex.y>=0&&nex.y<N&&vis[nex.x][nex.y]==0) { if(i == 0 && area[temp].up) ///当前节点有朝上方的管道,并且搜索方向向上 { if(area[Map[nex.x][nex.y]].down) ///看下一节点有没有朝下的管道 { vis[nex.x][nex.y] = 1; qu.push(nex); } } if(i == 1 && area[temp].right) ///搜索方向向右,且有朝右的管道 { if(area[Map[nex.x][nex.y]].left) { vis[nex.x][nex.y] = 1; qu.push(nex); } } if(i == 2 && area[temp].down) ///当前搜索方向朝下,且有朝下的管道 { if(area[Map[nex.x][nex.y]].up) { vis[nex.x][nex.y] = 1; qu.push(nex); } } if(i == 3 && area[temp].left) ///当前搜索方向朝左,且有朝左的管道 { if(area[Map[nex.x][nex.y]].right) { vis[nex.x][nex.y] = 1; qu.push(nex); } } } } }}int main(){ char ch; Init(); ///先给出每种土地下面管道的形态 while(~scanf("%d%d",&M,&N)) { if(M == -1 && N == -1) break; memset(vis,0,sizeof(vis)); for(int i = 0; i < M; i++) for(int j = 0; j < N; j++) { scanf(" %c",&ch); Map[i][j] = ch - 'A'; } int ans = 0; for(int i = 0; i < M; i++) for(int j = 0; j < N; j++) { if(vis[i][j] == 0) { ans++; bfs(i,j); } } printf("%d\n",ans); } return 0;}
2.并查集解法。
#include <iostream>#include <stdio.h>#include <string.h>#include <string>#include <math.h>#include <queue>#include <stdlib.h>#define INF 0x3f3f3f3fusing namespace std;const int MAXN = 55;int Map[MAXN][MAXN];int M,N;struct node{ int up; ///上 int down; ///下 int left; ///左 int right; ///右}area[13];void Init(){ memset(area,0,sizeof(area)); area[0].up = 1; area[0].left = 1; area[1].up = 1; area[1].right = 1; area[2].left = 1; area[2].down = 1; area[3].down = 1; area[3].right = 1; area[4].up = 1; area[4].down = 1; area[5].left = 1; area[5].right = 1; area[6].up = 1; area[6].left = 1; area[6].right = 1; area[7].up = 1; area[7].left = 1; area[7].down = 1; area[8].left = 1; area[8].right = 1; area[8].down = 1; area[9].up = 1; area[9].down = 1; area[9].right = 1; area[10].up = 1; area[10].down = 1; area[10].left = 1; area[10].right = 1;}typedef struct Set{ int rrank; int parent;}UFSTree;UFSTree t[MAXN*MAXN]; ///t[i]代表第i块田地。这里空间要开成MAXN*MAXNvoid MAKE_SET(UFSTree t[],int n){ for(int i = 0; i < n; i++) { t[i].rrank = 0; t[i].parent = i; }}int FIND_SET(UFSTree t[],int x){ if(x != t[x].parent) return FIND_SET(t,t[x].parent); else return x;}void UNION(UFSTree t[],int x,int y){ if(t[x].rrank > t[y].rrank) t[y].parent = x; else { t[x].parent = y; if(t[x].rrank == t[y].rrank) t[y].rrank++; }}int main(){ char ch; Init(); ///先给出每种土地下面管道的形态 while(~scanf("%d%d",&M,&N)) { if(M == -1 && N == -1) break; for(int i = 0; i < M; i++) for(int j = 0; j < N; j++) { scanf(" %c",&ch); Map[i][j] = ch - 'A'; } MAKE_SET(t,M*N); ///有M*N块田 int temp1,temp2; for(int i = 0; i < M; i++) for(int j = 0; j < N; j++) { if(j+1<N) ///该点与该点下侧的田地 { temp1 = i*N+j; temp2 = i*N+j+1; if(area[Map[i][j]].right && area[Map[i][j+1]].left) { temp1 = FIND_SET(t,temp1); temp2 = FIND_SET(t,temp2); if(temp1 != temp2) UNION(t,temp1,temp2); } } if(i+1<M) ///该点与该点右侧的田地 { temp1 = i*N+j; ///第temp1块田 temp2 = (i+1)*N+j; ///第temp2块田 if(area[Map[i][j]].down && area[Map[i+1][j]].up) { temp1 = FIND_SET(t,temp1); temp2 = FIND_SET(t,temp2); if(temp1 != temp2) ///两块田不在一个分离集合树 UNION(t,temp1,temp2); } } } int ans = 0; for(int i = 0; i < M*N; i++) { if(t[i].parent == i) ans++; } printf("%d\n",ans); } return 0;}
0 0
- HDU 1198 Farm Irrigation
- hdu 1198 Farm Irrigation
- hdu 1198 Farm Irrigation
- HDU--1198Farm Irrigation
- hdu 1198 Farm Irrigation
- HDU 1198-Farm Irrigation
- HDU 1198 Farm Irrigation
- hdu 1198 Farm Irrigation
- hdu 1198 Farm Irrigation
- HDU 1198 Farm Irrigation
- HDU 1198 Farm Irrigation
- HDU 1198 Farm Irrigation
- hdu 1198 Farm Irrigation
- hdu 1198 Farm Irrigation
- hdu 1198 Farm Irrigation
- hdu 1198 Farm Irrigation
- hdu(1198)Farm Irrigation
- hdu 1198 Farm Irrigation
- 【框架基础】java反射详解
- 写教程参考文章
- IMWeb训练营作业——todolist
- ZOJ 3471 状压DP
- 卷积神经网络(CNN)基础介绍
- HDU 1198:Farm Irrigation
- 求出最小的n个合数(n是键盘输入的任意正整数)的算法
- 《用python写网络爬虫》--网页抓取方法
- 抓包工具fiddler
- 中特基础整理
- 数据结构课下复习3
- 机器学习练习一:简单线性回归
- IOS学习(1)— IOS默认工程结构
- D. Police Stations----多起点bfs