Codeforces Round #375 (Div. 2) - D
题目链接:http://codeforces.com/contest/723/problem/D
题意:给定n*m小大的字符矩阵。'*'表示陆地,'.'表示水域。然后湖的定义是:如果水域完全被陆地包围则称为湖。 海的定义:如果水域与任何一个边界的水域有连通则陈伟海。现在要求填一些湖使得最后湖的数量恰好等于K.输出最小要填多少个单位的'.'水域和最终填完之后的字符矩阵。
思路:水题。注意本题的连通是四个方向[上下左右],然后dfs每一个连通块,对于每个连通块我们维护2个值:水域的数目和连通块属于海还是湖。 假装最终一共有x个湖。则要填(x-k)个湖。所以对于湖我们找水域最小的哪些连通块来填。
#define _CRT_SECURE_NO_DEPRECATE #include<stdio.h> #include<string.h> #include<cstring> #include<algorithm> #include<queue> #include<math.h> #include<time.h> #include<map> #include<vector> #include<iostream> using namespace std; typedef long long int LL; const int INF = 0x3f3f3f3f; const int MAXN = 50 + 10; int n, m, k, vis[MAXN][MAXN], id; char G[MAXN][MAXN]; int dist[4][2] = { 0, 1, 0, -1, 1, 0, -1, 0 }; struct Node{ int cnt; //水域数目 bool flag; //true: 海 false:湖 }sea[MAXN*MAXN]; bool check(int x, int y){ //是否越界 return x >= 0 && x<n&&y >= 0 && y<m; } void dfs(int x, int y){ int nextx, nexty; for (int i = 0; i<4; i++){ nextx = x + dist[i][0]; nexty = y + dist[i][1]; if (check(nextx, nexty) && G[nextx][nexty] != '*'&&!vis[nextx][nexty]){ vis[nextx][nexty] = id; sea[id].cnt++; if (nextx == 0 || nextx == n - 1 || nexty == 0 || nexty == m - 1){ sea[id].flag = true; //连通块包括边界。属于海 } dfs(nextx, nexty); } } } int main(){ while (~scanf("%d%d%d", &n, &m, &k)){ for (int i = 0; i<n; i++){ scanf("%s", G[i]); } memset(vis, 0, sizeof(vis)); id = 1; for (int i = 0; i<n; i++){ if (i == 0 || i == n - 1){ continue; } for (int j = 0; j<m; j++){ if (j == 0 || j == m - 1){ continue; } if (G[i][j] == '.'&&!vis[i][j]){ sea[id].cnt = 1; sea[id].flag = false; vis[i][j] = id; dfs(i, j); id++; } } } int totk = 0;//统计有多少湖 for (int i = 1; i<id; i++){ if (sea[i].flag == false){ totk++; } } int ans = 0; //统计要填多少单位的水域 for (; totk>k; totk--){ int minval = INF, minid = 0; for (int i = 1; i<id; i++){//枚举每一个连通块, if (sea[i].flag == false){//选择湖中水域最小的湖来填 if (sea[i].cnt<minval){ minval = sea[i].cnt; minid = i; } } } ans += minval; sea[minid].flag = true; //填完的湖标记一下。 for (int i = 0; i<n; i++){ for (int j = 0; j<m; j++){ if (vis[i][j] == minid){ //找到要填的湖的连通分量 G[i][j] = '*'; } } } } printf("%d\n", ans); for (int i = 0; i<n; i++){ printf("%s\n", G[i]); } } return 0; }