CodeForces - 723D - D. Lakes in Berland

蔚落 2022-06-12 12:59 233阅读 0赞

题目连接:http://codeforces.com/problemset/problem/723/D

题目描述

Description

The map of Berland is a rectangle of the size n × m, which consists of cells of size 1 × 1. Each cell is either land or water. The map is surrounded by the ocean.

Lakes are the maximal regions of water cells, connected by sides, which are not connected with the ocean. Formally, lake is a set of water cells, such that it’s possible to get from any cell of the set to any other without leaving the set and moving only to cells adjacent by the side, none of them is located on the border of the rectangle, and it’s impossible to add one more water cell to the set such that it will be connected with any other cell.

You task is to fill up with the earth the minimum number of water cells so that there will be exactly k lakes in Berland. Note that the initial number of lakes on the map is not less than k.

遥远的西方有一座小岛,小岛的四周环绕海洋,小岛可用一个n*m的矩阵描述,每一个小区块要么是水域,要么是陆地。

我们定义湖泊为一个封闭的水域联通区间,换句话说:如果一片水域互相联通,且被陆地包围并不和海洋连通,那么这整片水域就是一个湖泊。

由于小岛人口密度急剧上升,岛主决定填湖造陆,使得湖泊数量变为k,保证原来的湖泊数量是不小于k的。

现在,请你帮忙岛主求出,最少需要填多少块水域才能满足岛主的需要。

Input

The first line of the input contains three integers n, m and k (1 ≤ n, m ≤ 50, 0 ≤ k ≤ 50) — the sizes of the map and the number of lakes which should be left on the map.

The next n lines contain m characters each — the description of the map. Each of the characters is either ‘.’ (it means that the corresponding cell is water) or ‘*’ (it means that the corresponding cell is land).

It is guaranteed that the map contain at least k lakes.

第一行三个整数 n, m , k (1 ≤ n, m ≤ 50, 0 ≤ k ≤ 50)

接下来n行每行1个字符串,长度为m,描述这个小岛,其中’*’表示陆地,’.’表示水域

Output

In the first line print the minimum number of cells which should be transformed from water to land.

In the next n lines print m symbols — the map after the changes. The format must strictly follow the format of the map in the input data (there is no need to print the size of the map). If there are several answers, print any of them.

It is guaranteed that the answer exists on the given data.

第一行一个整数,表示最少需要填的水域数量。

接下来n行每行1个字符串,长度为m,描述填完以后的小岛地图。

如果有多组解,输出任意一组。

Sample Input

  • 5 4 1
  • \**
  • ..
  • \**
  • \.*
  • ..**

Sample Output

  • 1
  • \**
  • ..
  • \**
  • \**
  • ..**

解题思路

用一个结构体记录一个点(x,y)dfs开始的地方,也就是一个湖的开始,s记录湖的面积,(每次bfs时加1)
用一个全局变量 num,记录湖的个数(当湖为正确的湖的时候)
那么问题来了,那种不算湖的怎么办,在bfs里面判断出界的时候把初始为1 的flag边为0,意思是,如果一个湖它能出界,那么一定到了地图的边缘,在地图边缘的湖是一定不算湖的,所以如果能bfs到出界,一定要经过边缘,所以标记这个湖,不计入总湖数,而且要把面积记为0。
做完这些后,我们根据结构体中的s(面积)排序,用 湖的数量 - k, 得到的是需要填的湖的数量,从小开始填,然后记录每次填的面积,填湖的时候bfs填,因为已经记录了开始的点,所以这个bfs比较简单,只需要判断是否为点(水)就行,每次开始bfs的时候把这个点的map更改为*。

AC代码

  1. #include<iostream>
  2. #include<algorithm>
  3. #include<string.h>
  4. using namespace std;
  5. int n, m, k, num, flag, area = 0;
  6. char map[60][60];
  7. int vis[60][60];
  8. int to[4][2] = {0,1,0,-1,1,0,-1,0};
  9. struct node {
  10. int x, y, s;
  11. }cnt[6000];
  12. int cmp(node a, node b){
  13. return a.s < b.s;
  14. }
  15. void bfs(int x, int y) {
  16. vis[x][y] = 1;
  17. area++;
  18. for(int i = 0; i < 4; i++) {
  19. int tx = x + to[i][0];
  20. int ty = y + to[i][1];
  21. if(tx<0 || ty<0 || tx>n-1 || ty>m-1) {
  22. area = 0, flag = 0;
  23. continue;
  24. }
  25. if(map[tx][ty] == '*' || vis[tx][ty])
  26. continue;
  27. bfs(tx, ty);
  28. }
  29. }
  30. void bfs1(int x, int y) {
  31. map[x][y] = '*';
  32. for(int i = 0; i < 4; i++) {
  33. int tx = x + to[i][0];
  34. int ty = y + to[i][1];
  35. if(map[tx][ty] == '.') {
  36. bfs1(tx, ty);
  37. }
  38. }
  39. }
  40. int main () {
  41. scanf("%d %d %d", &n, &m, &k);
  42. num = 0;
  43. area = 0;
  44. memset(vis, 0, sizeof(vis));
  45. for(int i = 0; i < n; i++) {
  46. scanf("%s", map[i]);
  47. }
  48. for(int i = 0; i < n; i++) {
  49. for(int j = 0; j < m; j++) {
  50. area = 0, flag = 1;
  51. if(map[i][j] == '.' && !vis[i][j]) {
  52. bfs(i, j);
  53. if(flag) {
  54. cnt[num].x = i;
  55. cnt[num].y = j;
  56. cnt[num++].s = area;
  57. }
  58. }
  59. }
  60. }
  61. sort(cnt, cnt+num, cmp);
  62. int index = num - k;
  63. int sum = 0;
  64. for(int i = 0; i < index; i++) {
  65. sum += cnt[i].s;
  66. bfs1(cnt[i].x, cnt[i].y);
  67. }
  68. printf("%d\n", sum);
  69. for(int i = 0; i < n; i++) {
  70. printf("%s\n", map[i]);
  71. }
  72. return 0;
  73. }

发表评论

表情:
评论列表 (有 0 条评论,233人围观)

还没有评论,来说两句吧...

相关阅读

    相关 CodeForces1214D

    [CodeForces1214D][] 这个题据我所知有两种比较优秀的做法. 第一种是\\(DP\\)统计每个点的路径数,然后找出必经点,再从必经点开始\\(bfs\\

    相关 CodeForces1208D

    CodeForces1208D 也是挺吓人的一道题,我一开始以为给的是每个数字前比它小的数字有几个,然后我就苦苦看不懂样例... 然后我冷静了一下,重新分析,读题,发现

    相关 codeforces 25C. Roads in Berland

    有n个城市,每个城市都能到达别的城市,n\n的矩阵表明i到j城市的最短距离,现在要建造一些新的道路,在两个城市之间。问每次建造这些道路之后每两个城市之间的距离之和为多少。 如

    相关 Codeforces 496D

    题意 -------------------- 进行若干场比赛,每次比赛两人对决,赢的人得到1分,输的人不得分,先得到t分的人获胜,开始下场比赛,某个人率先赢下s场比赛