Maze CodeForces - 377A

Maze

 题目链接: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是认准一个方向后闭着眼走到头,当走不动了就返回上一个岔路口,然后再选择一条路走,它并不能存储所有内容,因为当你走到头再后退时,该点的的记录也就随着你的后退而消去了, 下面是两种搜索的示意图;

Maze CodeForces - 377A_第1张图片 Maze CodeForces - 377A_第2张图片

                         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

 

你可能感兴趣的:(搜索)