题意:给你一张n×m的图,点代表水,星代表地,当水连在一块时,称为湖,但是,若湖中有水在边界上,则不算它是湖,现在要求你去掉x个湖,并用地将其填上,使原图剩下k个湖,输出你最少需要多少个单位的地,并且输出你填补过的图。
比赛的时候没过,好菜呀。
思路:首先定义两个数组bfs_vis,dfs_vis,分别记录bfs和dfs的访问状况,定义flag,true代表一块区域属于湖,false代表一块区域不属于湖,vector[top]记录第top个湖内的点的情况,top初始化为0。
然后说下dfs的思路,从一个'.'点出发,并且只走'.',若其走到了边界上,则标记flag为false,此时并不结束dfs,而是继续走,将这一整块水域全部走完,并且dfs_vis都标记为true代表已经走过。相反,若走不到边界上,则一定能走完这个水域,flag为true,在dfs的同时,将走过的每一个点都装入vec[top]。当dfs完成后,若flag为false,则清空vec[top],否则top++,进入下个vec[top]记录新的湖。
然后说bfs,就是从(1,1)开始遍历,若找到一个点'.',并且其dfs_vis为false的话,说明它没有在dfs中被访问过,则对其进行dfs,当dfs完成后,若flag为true,说明这个点所在水域为湖,则记录它的大小和序号。
最后只要对这些湖的大小进行升序排序,并且相应的将其中的点填上就行了。
为什么这么强调dfs_vis呢,因为我就坑在这啦,最开始的时候,我在dfs中一旦发现某个点走到了边界就立即停止dfs并返回false,这样出现的问题就是当一个水域只有一个点在边界的时候,假如我们第一次就dfs到了改点,那么就相当于将其变成了陆地。则其剩下的水域在下一次dfs的时候就会被判定为一个湖。
代码:
#include<bits/stdc++.h>
#define MEM(a,x) memset(a,x,sizeof(a));
#define MEMINF(a) memset(a,0x3f,sizeof(a));
using namespace std;
typedef long long LL;
const int MAXN=4000;
const int INF=0x3f3f3f3f;
const int MOD=1000000007;
int n,m,k;
char mp[MAXN][MAXN];
int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};
int top;
struct node {
int x,y;
};
bool bfs_vis[MAXN][MAXN];
bool dfs_vis[MAXN][MAXN];
bool cmp(node a,node b) {
return a.x<b.x;
}
vector<node>que;
queue<node>q;
vector<node> vec[MAXN];
bool flag;
void dfs(node u) {
vec[top].push_back(u);
dfs_vis[u.x][u.y]=1;
if (u.x==1||u.x==n||u.y==1||u.y==m) flag=false;
for (int i=0; i<4; ++i) {
node v=u;
v.x+=dx[i];
v.y+=dy[i];
if (dfs_vis[v.x][v.y])continue;
if (mp[v.x][v.y]!='.') continue;
//printf("%d %d\n",v.x,v.y);
if (v.x==1||v.x==n||v.y==1||v.y==m) flag=false;
dfs(v);
}
}
void bfs(){
node u;
u.x=1,u.y=1;
q.push(u);
bfs_vis[1][1]=1;
MEM(bfs_vis,0);
while(!q.empty()) {
node no=q.front();
q.pop();
//printf("m %c %d\n",mp[4][3],!dfs_vis[4][3]);
if (mp[no.x][no.y]=='.'&&!dfs_vis[no.x][no.y]) {
flag=true;
//puts("-----");
dfs(no);
if (flag) {
//printf("no:%d %d\n",no.x,no.y);
//puts("*****");
node lal;
lal.x=vec[top].size();
lal.y=top;
que.push_back(lal);
top++;
}
else {
vec[top].clear();
}
}
for (int i=0; i<4; ++i) {
node v=no;
v.x+=dx[i];
v.y+=dy[i];
if (bfs_vis[v.x][v.y])continue;
if (v.x<1||v.x>n||v.y<1||v.y>m) continue;
q.push(v);
bfs_vis[v.x][v.y]=1;
}
}
}
int main() {
scanf("%d %d %d",&n,&m,&k);
top=0;
for (int i=1; i<=n; ++i) {
scanf("%s",mp[i]+1);
}
bfs();
//printf("MAP%ld\n",que.size());
int sum=0;
sort(que.begin(),que.end(),cmp);
for (auto i=0; i<top-k; ++i) {
sum+=que[i].x;
int num=que[i].y;
for (int it=0;it<vec[num].size(); ++it) {
int x=vec[num][it].x;
int y=vec[num][it].y;
mp[x][y]='*';
}
}
printf("%d\n",sum);
for (int i=1; i<=n; ++i)
puts(mp[i]+1);
}