题目链接:CodeForces - 377A
题意:给出一个N*M的地图,'·'表示空地,'#'表示墙,要求将k个空地转化成墙,并且最终的地图中空地是连通的;
思路:本题两种方法,DFS, BFS均可,DFS代码简练,但是理解起来有一定难度;BFS代码略显冗杂,但是容易理解;
先说BFS:
题目最终要求是剩余的空地是连续的,而我们同样可以求出最后剩余的空地的数量,反向思维一下,找出连通的相应数量的空地,其他空地就是要转化的了;标记不需转化的空地;
#include
using namespace std;
int nxt[4][2]={1, 0, 0, 1, -1, 0, 0, -1};
char maze[510][510];
pair p;
queue > que, ans;
int vis[510][510];
int n, m, k, wall;
void bfs(int s_x, int s_y){
memset(vis, 0, sizeof(vis));
p=make_pair(s_x, s_y);
vis[s_x][s_y]=1;
while(!que.empty()) que.pop();
que.push(p);
while(!ans.empty()) ans.pop();
while(!que.empty()){
p=que.front();
que.pop();
ans.push(p);
if(ans.size()==n*m-k-wall){
break;
}
int x=p.first, y=p.second;
for(int i=0; i<4; i++){
int tx=x+nxt[i][0];
int ty=y+nxt[i][1];
if(tx<0||ty<0||tx>=n||ty>=m) continue;
if(vis[tx][ty]) continue;
if(maze[tx][ty]=='#') continue;
vis[tx][ty]=1;
que.push(make_pair(tx, ty));
}
}
while(!ans.empty()){
p=ans.front();
ans.pop();
maze[p.first][p.second]='+';
}
for(int i=0; i
然后就是DFS了;先思考一下,DFS还能按照上边的思路吗?先找出联通图,标记,再转化剩余空地?
可以?还是不可以? 这样的想法当然是不可以的啦~~~想啥嘞,忘了dfs啥干啥的了?
dfs是认准一个方向后闭着眼走到头,当走不动了就返回上一个岔路口,然后再选择一条路走,它并不能存储所有内容,因为当你走到头再后退时,该点的的记录也就随着你的后退而消去了, 下面是两种搜索的示意图;
DFS BFS
那么DFS怎么写呢?观察一下上边的图,每次dfs一定会先走到一条路的终点然后退回上一次的岔路口,那么如果我们再dfs后退时将他后退的那个格子转化成墙,那么剩下的空地必定是联通的,然后就转化K个空地就ok了;
#include
using namespace std;
int n, m, k;
char maze[510][510];
int vis[510][510];
void dfs(int x, int y){
if(x<0||y<0||x>=n||y>=m) return;
if(maze[x][y]!='.') return;
if(vis[x][y]) return;
vis[x][y]=1;
dfs(x+1, y);
dfs(x, y+1);
dfs(x-1, y);
dfs(x, y-1);
//当dfs再也无路可走时就开始转化空地;
if(k) maze[x][y]='X', k--;
}
int main(){
scanf("%d%d%d", &n, &m, &k);
for(int i=0; i