深搜02 Fire Net

Suppose that we have a square city with straight streets. A map of a city is a square board with n rows and n columns,
each representing a street or a piece of wall.
A blockhouse is a small castle that has four openings through which to shoot. The four openings are facing North, East,
South, and West, respectively. There will be one machine gun shooting through each opening.
Here we assume that a bullet is so powerful that it can run across any distance and destroy a blockhouse on its way. On
the other hand, a wall is so strongly built that can stop the bullets.
The goal is to place as many blockhouses in a city as possible so that no two can destroy each other. A configuration
of blockhouses is legal provided that no two blockhouses are on the same horizontal row or vertical column in a mapunless
there is at least one wall separating them. In this problem we will consider small square cities (at most 4x4) that contain
walls through which bullets cannot run through.
The following image shows five pictures of the same board. The first picture is the empty board, the second and third
pictures show legal configurations, and the fourth and fifth pictures show illegal configurations. For this board, the
maximum number of blockhouses in a legal configuration is 5; the second picture shows one way to do it, but there are
several other ways.
Your task is to write a program that, given a description of a map, calculates the maximum number of blockhouses that
can be placed in the city in a legal configuration.
输入
The input file contains one or more map descriptions, followed by a line containing the number 0 that signals the end
of the file. Each map description begins with a line containing a positive integer n that is the size of the city; n will
be at most 4. The next n lines each describe one row of the map, with a '.' indicating an open space and an uppercase
'X' indicating a wall. There are no spaces in the input file.
输出
For each test case, output one line containing the maximum number of blockhouses that can be placed in the city in a legal
configuration.
样例输入
4
.X..
....
XX..
....
2
XX
.X
3
.X.
X.X
.X.
3
...
.XX
.XX
4
....
....
....
....
0
样例输出
5
1
5
2
4

翻译:

假设我们有一个街道笔直的广场城市。城市地图是一块有n行n列的正方形板,每个代表一条街道或一堵墙。
碉堡是一座有四个开口的小城堡。四个开口朝北、朝东,分别是南部和西部。每个开口都有一把机关枪。
在这里,我们假设一颗子弹是如此强大,以至于它可以跑过任何距离,在途中摧毁一座碉堡。另一方面,一堵墙非常坚固,可以挡住子弹。
我们的目标是在一个城市里安置尽可能多的碉堡,这样就不会有两个互相毁灭。
如果地图上没有两个碉堡位于同一水平行或垂直列上,则碉堡的数量是合法的,除非至少有一面墙将它们隔开。
在这个问题中,我们将考虑包含子弹无法穿过的墙。下图显示了同一块板的五张图片。
第一张图是空板,第二张和第三张图片显示合法配置,第四张和第五张图片显示非法配置。
对于这个,合法配置中的最大拦污栅数量为5个;第二张图片显示了一种方法,但有其他几种方法。
您的任务是编写一个程序,在给定地图描述的情况下,计算可以在城市中进行合法配置。
输入
输入文件包含一个或多个映射描述,后跟一行,其中包含表示结束的数字0
每个地图描述都以一行开头,该行包含一个正整数n,即城市的大小;n将最多4岁。
接下来的n行分别描述了地图的一行,其中“.”表示一个开放空间和一个大写字母。
“X”表示墙。输入文件中没有空格。
输出
对于每个测试用例,输出一行,其中包含可以在城市中合法放置的最大拦污栅数量。

分析:采用递归+回溯的方法。

不妨先遍历第一行,再遍历第二行,然后依次类推。从下图可以看出x和y轴的正方向,所以判断一个点是否可以放置碉堡时,可以从(x,y)出向左和向上搜索。搜索过之后,就可以得知(x,y)出是否可以放置,这是一条分支。另一条分支是直接搜索下一个点。这两条分支不是if和else的关系,而是同时都发生的关系。

代码:

#include<cstdio>
using namespace std;
char map[4][4];
int n,max;
int legalPosition(int x,int y) { //网x减小的方向和y减小的方向搜索,即向左和向上搜索
	if(map[x][y]=='X') return 0;
	for(int i=x-1; i>=0; i--) {
		if(map[i][y]=='b') return 0;
		else if(map[i][y]=='X') break;
	}
	for(int i=y-1; i>=0; i--) {
		if(map[x][i]=='b') return 0;
		else if(map[x][i]=='X') break;
	}
	return 1;//如果之前没有出现错误,则现在返回1
}
void dfs(int position,int current) {
	if(position==n*n) { //如果把city的所有位置都遍历完了
		if(current > max) max=current;
		return;
	}
	int x=position/n;//获取该position对应的坐标(x,y)
	int y=position%n;
	if(legalPosition(x,y)) {//(x,y)处可放置blackhouse,这时第一个分支
		map[x][y]='b';
		dfs(position+1,current+1);
		map[x][y]='.';//回溯
	}
	/*注意:该语句前不加else,如果加了else,
	则就相当于去除了递归的一个分支,使得递归只有一条分支 ,不能解决问题*/
	dfs(position+1,current);//直接搜索下一个点
}
int main() {
	freopen("in.txt","r",stdin);
	while(scanf("%d",&n)&&n!=0) {
		max=0;
		getchar();
		for(int i=0; i<n; i++) {
			for(int j=0; j<n; j++) {
				scanf("%c",&map[i][j]);
			}
			getchar();
		}
		dfs(0,0);
		printf("%d\n",max);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/jiuweideqixu/article/details/88073395