码迷,mamicode.com
首页 > 其他好文 > 详细

AOJ 0118 Property Distribution

时间:2020-11-21 11:56:29      阅读:4      评论:0      收藏:0      [点我收藏+]

标签:while   应该   ios   print   解决   列表   distrib   void   eof   

原题目简介

タナカ氏が HW アールの果樹園を残して亡くなりました。果樹園は東西南北方向に H × W の区画に分けられ、区画ごとにリンゴ、カキ、ミカンが植えられています。タナカ氏はこんな遺言を残していました。

果樹園は区画単位でできるだけ多くの血縁者に分けること。ただし、ある区画の東西南北どれかの方向に### となりあう区画に同じ種類の果物が植えられていた場合は、区画の境界が分からないのでそれらは 1 つ### の大きな区画として扱うこと。

例えば次のような 3 × 10 の区画であれば (‘リ‘はリンゴ、‘カ‘はカキ、‘ミ‘はミカンを表す)

同じ樹がある区画の間の境界を消すと次のようになり、

結局 10 個の区画、つまり 10 人で分けられることになります。

雪が降って区画の境界が見えなくなる前に分配を終えなくてはなりません。あなたの仕事は果樹園の地図### をもとに分配する区画の数を決めることです。

果樹園の地図を読み込み、分配を受けられる血縁者の人数を出力するプログラムを作成してください。


Input

複数のデータセットが与えられます。各データセットは空白で区切られた H, W (H, W ≤ 100) を含む### 行から始まり、続いて H × W の文字からなる H 行の文字列が与えられます。この文字列には、リンゴ### を表す ‘@‘、カキを表す ‘#‘、ミカンを表す ‘*‘、の 3 文字しか現れません。

入力はゼロが2つの行で終わります。データセットの数は 20 を超えません。


Output

各データセットごとに、分配を受ける人数を1行に出力してください。


Sample Input

10 10

####*****@

@#@@@@##

@##**@@@

#***#@**

##@#@@##

@@@@@@@#

*#@@##

@@@@@##@

@#*@##**

@****#@@#@

0 0


Output for the Sample Input

33


原题目翻译如下:

转: 题意:在H * W的矩形果园里有苹果、梨、蜜柑三种果树, 相邻(上下左右)的同种果树属于同一个区域,给出果园的果树分布,求总共有多少个区域。 (原题的样图中苹果为リ,梨为カ,蜜柑为ミ, 图中共10个区域) 输入:多组数据,每组数据第一行为两个整数H、W(H <= 100, W <= 100), H =0 且 W = 0代表输入结束。以下H行W列表示果园的果树分布, 苹果是@,梨是#, 蜜柑是*。 输出:对于每组数据,输出其区域的个数。


思路如下:

这道题还是dfs的经典习题,但是跟以往有些不同的是:统计区域的类型有多种,因此我们需要以不同类型区域的果树为起点,进行深度优先遍历。最后,每统计一个类型区域的果树(也可以理解为每进行一次dfs),我们就将其区域的个数+1。其中,统计果树的区域可以重复,因为在原题中果树的区域分布不是在一起的而是分散的。具体可以见图:

技术图片

我们可以以“力”这个类型来举例,在这张分布图中,“力”的分布区域不是在一起的,是分散的。(在图中的“力”的区域共有三片)因此,一定要注意,不能统计完一次“力”后,就不再进行统计了,因为有可能“力”的区域有多片。

所以,为了解决这个问题,我们可以利用双重循环来统计图中所有的区域,每统计完一次区域后,就将其替换成".",以免被重复遍历到。

如若不能理解的话,请参考代码进行思考一下,应该就能明白什么意思了。


代码如下:

#include <iostream>
#include <cstdio>
using namespace std;
char Graph[100][100];
int h, w;
int Count=0;   //代表区域的个数(初始化为0)
void dfs(int x, int y, char flag);    //代表进行深度优先搜索的函数,其中flag代表要进行查找的果树类型

void dfs(int x, int y, char flag)
{
	int movex, movey;    //代表移动之后的坐标
	int i, j;
	Graph[x][y] = ‘.‘;  //将搜索完之后的果树用.代替,免得被重复遍历到,最终影响题目结果
	for (i = -1; i <= 1; i++)
	{
		for (j = -1; j <= 1; j++)
		{
			if (i == 0 || j == 0)   //筛选四个方向(-1,0)(1,0)(0,-1)(0,1)
			{
				movex = x + i;
				movey = y + j;
				if (movex >= 0 && movex < h && movey >= 0 && movey < w && Graph[movex][movey] == flag)
				{
					dfs(movex, movey, flag);   //继续向下进行深度优先搜索
				}
			}
		}
	}
}

int main()
{
	int i, j;
	char x;
	while (scanf("%d %d", &h, &w) != EOF)
	{
		if (h == 0 && w == 0)
		{
			return 0;
		}
		else
		{
			for (i = 0; i < h; i++)
			{
				for (j = 0; j < w; j++)
				{
					cin >> x;
					Graph[i][j] = x;
				}
			}
			for (i = 0; i < h; i++)
			{
				for (j = 0; j < w; j++)
				{
					if (Graph[i][j] == ‘@‘)   //查找苹果
					{
						dfs(i, j, ‘@‘);       //以苹果为起点进行深度优先搜索
						Count++;              //查找完后,区域个数+1
					}
					else if (Graph[i][j] == ‘#‘) //查找梨
					{
						dfs(i, j, ‘#‘);
						Count++;
					}
					else if (Graph[i][j] == ‘*‘) //查找蜜柑
					{
						dfs(i, j, ‘*‘);
						Count++;
					}
				}
			}
			printf("%d\n", Count);    //果树遍历完之后输出结果
			Count = 0;                //当一次测试实例运行完之后,我们要将区域个数清0,不然的话会影响下一次的结果

		}
	}
}

AOJ 0118 Property Distribution

标签:while   应该   ios   print   解决   列表   distrib   void   eof   

原文地址:https://www.cnblogs.com/gao79135/p/13992454.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!