【CodeForces - 616C 】The Labyrinth点石成金(并查集,dfs)
題干:
小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。
總結
以上是生活随笔為你收集整理的【CodeForces - 616C 】The Labyrinth点石成金(并查集,dfs)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【POJ - 2096】Collecti
- 下一篇: 暴雨红色预警!青岛街道积水齐腰、有车辆水