题目大意:每一块由'*'和’X‘组成的算骰子的一个面,其中X代表点数1,如果有连在一起的X算一起算点数1,有些类似油田问题的计数方式。计算各个面的点数,排序输出。
解题思路:先将所有’*‘或'X'标记,然后bfs遍历,其中遍历到X时,dfs将连着一起的‘X’变为‘*’(这样就不会因为进入dfs标记为访问过后,在bfs里没法遍历整面)。最后输出。
ac代码:
#include <iostream>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
int n, m, vis[60][60], re[5005], coun, cnt=1;
char map[60][60];
int dx[4]={-1,1,0,0}, dy[4]={0,0,-1,1};
queue <int>qu;
int dfs(int a, int b)
{
int t1, t2;
for (int i=0; i<4; i++){
t1 = a + dx[i];
t2 = b + dy[i];
if (map[t1][t2] == 'X')
map[t1][t2]='*', dfs(t1, t2);
}
return 1;
}
int bfs(int a, int b)
{
int sum=0;
while (!qu.empty())
qu.pop();
qu.push(a), qu.push(b);
while (!qu.empty()){
int x = qu.front();
qu.pop();
int y = qu.front();
qu.pop();
for (int i=0; i<4; i++)
if (vis[x+dx[i]][y+dy[i]]){
if (map[x+dx[i]][y+dy[i]] == 'X')
dfs(x+dx[i], y+dy[i]), sum++;
qu.push(x+dx[i]);
qu.push(y+dy[i]);
vis[x+dx[i]][y+dy[i]] = 0;
}
}
return sum;
}
int main()
{
while (scanf("%d%d", &n, &m)!=EOF){
if (!n || !m)
break;
memset(vis, 0, sizeof(vis));
coun = 0;
for (int i=0; i<m; i++)
scanf("%s", map[i]);
for (int i=0; i<m; i++)
for (int j=0; j<n; j++)
if (map[i][j]!='.')
vis[i][j] = 1;
for (int i=0; i<m; i++)
for (int j=0; j<n; j++)
if (vis[i][j])
re[coun++] = bfs(i, j);
sort(re, re+coun);
printf("Throw %d\n", cnt++);
for (int i=0; i<coun; i++)
printf(i==coun-1?"%d\n\n":"%d ", re[i]);
}
return 0;
}