• 算法实验题 5.1 湖泊


    问题描述
    G 最近开始对地理感兴趣,小 G 找来了伯兰的地图,并用网格将其划分。被划分后
    的地图是一个 n*m 的矩形。每一个单元格的大小是 1*1 的,每一格代表着水或者陆地。地
    图外则代表着海洋。湖泊是相邻的所有代表水的格子组成的不与海洋相邻的最大区域。地图
    上有着超过 k 的湖泊,小 G 想将其中的一些代表水的格子变为陆地,使得地图中只存在精
    确的 k 个湖泊,又不想改变太多的格子。所以,他请你帮忙计算使得地图中只存在 k 个湖泊
    所需要改变的最小格子数。
    ★数据输入
    输入的第一行为包括三个整数n,m,k(1 ≤ n, m ≤ 50, 0 ≤ k ≤ 50)表示地图的大小和需
    要保存的湖泊数量
    接下来 n 行,每行包括 m 个字符用来表示地图信息,只包括“.”“*”两种字符。( “.”
    表示水, “*”表示陆地)。
    输入数据保证原始的湖泊数量大于等于 k
    30%的数据 n*m<=30
    70%的数据 n*m<=200
    100%的数据 n*m<=2500

    题意:

    给n,m和k,n和m为所给矩阵的高和宽。k是要求最多剩下的湖的数量。
    在所给的矩阵中,*代表陆地,.代表水。
    湖的定义是一片连续的水(上下左右四个方向),并且水不含边界。
    水含边界的情况被成为海。
    问最少填多少湖的面积,使得湖的数量减少到k.

    海洋包围的小岛,岛内的有湖,'.'代表水,'*'代表陆地,给出的n*m的地图里至少有k个湖,求填掉面积尽量少的水,使得湖的数量正好为k。

    解题思路:先深搜DFS找出所有的湖泊,然后按照面积从小到大排序,若湖的数量为cnt,填掉前cnt-k个湖。

    #include<stdio.h>
    #include<string.h>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    //author:zeze 2016-12-11 13:24:39
    //DFS+Greedy
    struct lakes{
        int x,y;//lake site
        int num;//lake size
    }lake[2500];
    bool cmp(lakes a,lakes b){
        return a.num<b.num;
    }
    int sx[4]={0,0,-1,1};
    int sy[4]={-1,1,0,0};
    char map[51][51];
    bool vis[51][51];
    int num,cnt,ans,isLake;
    int n,m,k;
    void dfs(int x,int y){
        int xx,yy;
        vis[x][y]=1;
        num++;
        if(x==0||x==n-1||y==0||y==m-1)//link to ocean
            isLake=0;
        for(int i=0;i<4;i++){
            xx=x+sx[i];
            yy=y+sy[i];
            if(xx>=0&&xx<n&&yy>=0&&yy<m&&map[xx][yy]=='.'&&!vis[xx][yy])
                dfs(xx,yy);
        }
    }
    void fillLake(int x,int y){
        int xx,yy;
        vis[x][y]=1;
        ans++;
        map[x][y]='*';//fill this lake
        for(int i=0;i<4;i++){
            xx=x+sx[i];
            yy=y+sy[i];
            if(xx>=0&&xx<n&&yy>=0&&yy<m&&map[xx][yy]=='.'&&!vis[xx][yy])
                fillLake(xx,yy);
        }
    }
    int main(){
        int i,j,t;
        cnt=ans=0;
        scanf("%d %d %d",&n,&m,&k);
        for(i=0;i<n;i++)
            scanf("%s",map[i]);
        memset(vis,0,sizeof(vis));
        for(i=0;i<n;i++){
            for(j=0;j<m;j++){
                if(!vis[i][j]&&map[i][j]=='.'){//unVisit and isWater
                    isLake=1;
                    num=0;
                    dfs(i,j);
                    if(isLake){// Is Lake? Yes!
                        lake[cnt].x=i;
                        lake[cnt].y=j;
                        lake[cnt++].num=num;
                    }
                }
            }
        }
        sort(lake,lake+cnt,cmp);//sort lakes by num
        memset(vis,0,sizeof(vis));
        for(t=0;t<cnt-k;t++){//fill mini lake
            for(i=0;i<n;i++){
                for(j=0;j<m;j++){
                    if(i==lake[t].x&&j==lake[t].y){//unVisit and isWater
                        fillLake(i,j);
                    }
                }
            }
        }
        printf("%d
    ",ans);
        for(i=0;i<n;i++){
            printf("%s
    ",map[i]);
        }
        return 0;
    }
    #include<bits/stdc++.h>
    using namespace std;
    int n,m,k;
    char a[55][55];
    bool vis[55][55];
    int dx[6]={0,0,1,-1};
    int dy[6]={1,-1,0,0};
    
    int num,cnt,islake;
    int ans;
    
    struct lake{
        int x,y;
        int num;
        int id;
    }lk[2600];
    
    bool cmp(lake a,lake b){
        return a.num<b.num;
    }
    
    void dfs(int x,int y){
        vis[x][y]=1;
        num++;
        if(x==0||x==n-1||y==0||y==m-1)//形成海洋不是湖
            islake=0;
        for(int i=0;i<4;i++){
            int nx=x+dx[i],ny=y+dy[i];
            if(nx>=0&&nx<n&&ny<m&&ny>=0&&a[nx][ny]=='.'&&!vis[nx][ny])
                dfs(nx,ny);
        }
    }
    void fil(int x,int y,int id){
        vis[x][y]=1;
        ans++;
        a[x][y]='*';//填充这个湖
        for(int i=0;i<4;i++){
            int nx=x+dx[i],ny=y+dy[i];
            if(nx>=0&&nx<n&&ny<m&&ny>=0&&a[nx][ny]=='.'&&!vis[nx][ny])
                fil(nx,ny,id);
        }
    }
    int main(){
        cnt=0;
        scanf("%d%d%d",&n,&m,&k);
    
        for(int i=0;i<n;i++){
            scanf("%s",a[i]);
        }
        memset(vis,0,sizeof(vis));
    
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(!vis[i][j]&&a[i][j]=='.'){
                    num=0;
                    islake=1;
                    dfs(i,j);
                    if(islake)
                        lk[cnt++]=(lake){i,j,num,cnt};
                }
            }
        }
    
        memset(vis,0,sizeof(vis));
    
        sort(lk,lk+cnt,cmp);
    
        for(int l=0;l<cnt-k;l++){
    
            for(int i=0;i<n;i++){
                for(int j=0;j<m;j++){
                    if(i==lk[l].x&&j==lk[l].y)
                        fil(i,j,lk[l].id);//填充这个湖
                }
            }
    
        }
        printf("%d
    ",ans);
        for(int i=0;i<n;i++){
            printf("%s
    ",a[i]);
        }
    }
  • 相关阅读:
    Linux_LEMP
    Linux_LEMP
    Linux_指令杂烩
    Linux_指令杂烩
    Linux_SELinux使用
    AWS S3存储基于Hadoop之上的一致性保证
    Ozone数据写入过程分析
    Ozone Datanode的分布式元数据管理
    聊聊Ozone的Topology Awareness
    Ozone数据探查服务Recon的启用
  • 原文地址:https://www.cnblogs.com/zeze/p/6159461.html
Copyright © 2020-2023  润新知