練習題這道題,這是一道思路很明確的題(dfs裸題+簡單貪心),不過在實現細節上有些要注意的地方。
題目大意:在一個n×m的地方上有陸地和湖,那些和邊緣連接的水域視爲海,題目給出最後要保留k個湖,由你計算出最少要填多少陸地,並把圖畫出來。附鏈接:http://codeforces.com/problemset/problem/723/D
大體思路:計算出有num個湖,並記錄下最開始找到這個湖的位置和湖的面積,保存在一個數組Node[3000]裏,然後對Node數組排序,取出num-k個湖填滿,計算要填的總面積,最後輸出。思路很清晰。不過在判斷是否是湖這一點上需要想一想怎麼寫。
以下是ac代碼
#include<stdio.h>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
struct node{
int x,y;
int cnt;
}Node[3000];
const int maxn=60;
int n,m;
char box[maxn][maxn];
int vis[maxn][maxn];
int ans,flag;
int dx[]={0,1,0,-1};
int dy[]={1,0,-1,0};
int cmp(node a,node b){
return a.cnt<b.cnt;
}
void dfs(int bx,int by){ //判斷有多少個湖的函數
if(bx<=0||bx>=n-1||by<=0||by>=m-1){
flag=1;
return;
}
vis[bx][by]=1;
ans++;
for(int i=0;i<4;i++){
int x=bx+dx[i];
int y=by+dy[i];
if(box[x][y]=='.'&&!vis[x][y])
bfs(x,y);
}
}
void rdfs(int bx,int by){ //填湖的函數
if(bx<0||bx>=n||by<0||by>=m)
return;
box[bx][by]='*';
for(int i=0;i<4;i++){
int x=bx+dx[i];
int y=by+dy[i];
if(box[x][y]=='.')
rbfs(x,y);
}
}
int main(){
int k;
while(scanf("%d%d%d",&n,&m,&k)!=EOF){
memset(vis,0,sizeof(vis));
for(int i=0;i<n;i++)
scanf("%s",box[i]);
int num=0;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++){
if(box[i][j]=='.'&&!vis[i][j]){
ans=0;
flag=0; //判斷標誌
dfs(i,j);
if(!flag)
Node[num++]={i,j,ans};
}
}
/*
for(int i=0;i<num;i++)
printf("%d %d %d\n",Node[i].x,Node[i].y,Node[i].cnt);
*/
sort(Node,Node+num,cmp);
int sum=0;
for(int i=0;i<num-k;i++){
rdfs(Node[i].x,Node[i].y); //填湖
sum+=Node[i].cnt;
}
printf("%d\n",sum);
for(int i=0;i<n;i++)
printf("%s\n",box[i]);
}
return 0;
}