题干:
小O无意间发现了一张藏宝图,它跟随藏宝图的指引来到了一个宫殿,宫殿的地板被分成了n*m块格子,每个格子上放置了金子或者石头
藏宝图告诉小O,它可以选择一块石头变成金子,并且带走与变化后的金子联通区域的所有金子(联通指的是上下左右,不能斜着)
小O想计算一下点每个石头能带走的金子个数,帮帮他吧。
输入:
第一行两个数n,m (1 <= n,m <= 1000 )
随后n行,每行m个字符,表示宫殿地板上放置的物品,' * '表示放置的是石头,' . '表示放置的是金子
输出:
在每个石头位置输出如果将该位置点石成金,能带走的金子个数,方便起见,将这个数%10再输出
输入:
3 3
*.*
.*.
*.*
输出:
3.3
.5.
3.3
输入:
4 5
**..*
..***
.*.*.
*.*.*
输出:
46..3
..732
.6.4.
5.4.3
Note
In first example, if we imagine that the central cell is empty then it will be included to component of size 5 (cross). If any of the corner cell will be empty then it will be included to component of size 3 (corner).
解题报告:
搜索上并查集就可以了。注意统计的时候,有可能重复,比如
这样相同的答案会统计四次。所以要去重一下。
AC代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define ll long long
#define pb push_back
#define pm make_pair
using namespace std;
const int MAX = 1000 + 5;
char maze[MAX][MAX];
int ans[MAX][MAX];
bool vis[MAX][MAX];
int f[MAX*MAX];
int num[MAX*MAX];
int n,m;
int nx[4] = {0,1,0,-1};
int ny[4] = {1,0,-1,0};
int getf(int v) {
return v == f[v] ? v : f[v] = getf(f[v]);
}
void merge(int u,int v) {
int t1 = getf(u);
int t2 = getf(v);
f[t2] = t1;
}
int get(int x,int y) {
return (x-1)*m +y;
}
void go(int x,int y) {
for(int k = 0; k<4; k++) {
int tx = x + nx[k];
int ty = y + ny[k];
if(tx < 1 || tx > n || ty < 1 || ty > m) continue;
if(maze[tx][ty] == '*' || vis[tx][ty]) continue;
merge(get(x,y),get(tx,ty));
vis[tx][ty] = 1;
go(tx,ty);
}
}
int main()
{
cin>>n>>m;
for(int i = 0; i<=n*m; i++) {
f[i] = i;
}
for(int i = 1; i<=n; i++) {
scanf("%s",maze[i]+1);
}
for(int i = 1; i<=n; i++) {
for(int j = 1; j<=m; j++) {
if(maze[i][j] == '.' && vis[i][j] == 0) {
vis[i][j] = 1;
go(i,j);
}
}
}
for(int i = 1; i<=n; i++) {
for(int j = 1; j<=m; j++) {
if(maze[i][j] == '*') continue;
num[getf(get(i,j))]++;
}
}
for(int i = 1; i<=n; i++) {
for(int j = 1; j<=m; j++) {
if(maze[i][j] == '.') ans[i][j] = '.';
else {
int cnt = 0;
set<int> ss;
for(int k = 0; k<4; k++) {
int tx = i + nx[k];
int ty = j + ny[k];
if(maze[tx][ty] == '*')continue;
if(tx < 1 || tx > n || ty < 1 || ty > m) continue;
ss.insert(getf(get(tx,ty)));
}
auto it = ss.begin();
for(;it!=ss.end();++it) cnt += num[*it];
ans[i][j] = cnt;
}
}
}
for(int i = 1; i<=n; i++) {
for(int j = 1; j<=m; j++) {
if(maze[i][j] == '.') printf(".");
else printf("%d",(ans[i][j]+1)%10);
}
puts("");
}
return 0 ;
}
/*
16:00-16:13
*/
/*
4 1
*
.
*
.
*/
别忘了这样写的话,每个入口都要加上vis[][]=1;(指的是main函数里)
题目不难,但是还是WA了一发,映射的时候注意是(x-1)*m而不是(x-1)*n。