UVa 657 - The die is cast解题报告

题意:其中X和*一起称为区域I,在区域I中相连的X称为区域II , 输出就是输出m个数字,其中m就是区域I的个数,这m个数字中第i个数字num[i]表示某块区域I一面又多少个区域II。这道题就是简单图的搜索的加强版,因为需要先搜索确定区域|,再在区域|中搜索X区域。也就是双重搜索。

思路:先深搜*或X,然后判断X,如果是X再调用另一个搜索函数搜索X的区域,并把搜过的地方标为*。每次调用dfs1搜索*说明进入一个区域,每次调用dfs2搜索X说明在区域|中搜到一个X区域。


//657 - The die is cast
#include <iostream>
#include <cstring>
#include <stack>
#include <algorithm>
using namespace std;
int dir[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
struct nobe
{
	int x, y;
};
char grah[51][51];
bool visit[51][51];
int m, num[50];
void dfs1(int, int);
void dfs2(int, int);
int main()
{
	//freopen("data.txt", "r", stdin);
	int w, h, cases = 1;
	while (scanf("%d%d", &w, &h) && w && h)
	{
		memset(grah, 0, sizeof(grah));
		memset(visit, 0, sizeof(visit));
		memset(num, 0, sizeof(num));
		for(int i = 1; i <= h; i++)
			scanf("%s", grah[i]);
		m = 0;
		for(int i = 1; i <= h; i++)
			for(int j = 1; j <= w; j++)
				if((grah[i][j] == '*' || grah[i][j] == 'X') && !visit[i][j])
				{
					dfs1(i, j);//搜索*区域
					m++;
				}

		sort(num, num + m);
		printf("Throw %d\n", cases++);
		printf("%d", num[0]);//uva的测试很严格,多个空格都不行
		for(int i = 1; i < m; i++)
			printf(" %d", num[i]);
		printf("\n\n");
	}
	return 0;
}

void dfs1(int x, int y)
{
	stack<nobe> st;
	nobe temp;
	temp.x = x;
	temp.y = y;
	st.push(temp);
	
	while (!st.empty())
	{
		temp = st.top();
		st.pop();
		for(int i = 0; i < 4; i++)
		{
			int dx = temp.x + dir[i][0], dy = temp.y + dir[i][1];
			if(grah[dx][dy] == 'X')
			{
				dfs2(dx, dy);
				num[m]++;//更新X的数量
			}
			if(grah[dx][dy] == '*' && !visit[dx][dy])
			{
				visit[dx][dy] = true;
				nobe t;
				t.x = dx;
				t.y = dy;
				st.push(t);
			}
		}
	}
}

void dfs2(int x, int y)
{
	stack<nobe> st;
	nobe temp;
	temp.x = x;
	temp.y = y;
	st.push(temp);
	grah[x][y] = '*';
	while (!st.empty())
	{
		temp = st.top();
		st.pop();
		for(int i = 0; i < 4; i++)
		{
			int dx = temp.x + dir[i][0], dy = temp.y + dir[i][1];
			if(grah[dx][dy] == 'X')
			{
				nobe t;
				t.x = dx;
				t.y = dy;
				st.push(t);
				grah[dx][dy] = '*';
			}
		}
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值