题意:其中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] = '*';
}
}
}
}