HDU1045_Fire Net_深搜

来源:互联网 发布:中电科大数据研究院 编辑:程序博客网 时间:2024/05/20 12:46

Fire Net

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 11173    Accepted Submission(s): 6655


Problem Description
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 map unless 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. 
 

Input
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. 
 

Output
For each test case, output one line containing the maximum number of blockhouses that can be placed in the city in a legal configuration.
 

Sample Input
4.X......XX......2XX.X3.X.X.X.X.3....XX.XX4................0
 

Sample Output
51524
 

Source

大致题意:

1.给出一个正方形网格,其边长最大为4。

2.方格有两种状态,空白格子(.),带墙的格子(X)。

3.目标:在空白格子里放置尽可能多的碉堡,条件是碉堡之间不能相互攻击。

4.碉堡攻击规则:碉堡可以发射炮弹攻击上、下、左、右四个方向的碉堡,无视距离远近。但是炮弹不能打穿墙壁。

5.给出网格大小和初始状况,输出最大的可能碉堡数。


大致思路:

带回溯的深度优先搜索。从第一个格子开始检索,每个格子有 放碉堡 和 不放碉堡 两种选择(条件限制有的 方格不能放置碉堡,只有一种选择 不放置。)。由此进行递归。


解题过程:

这个题整体上还是比较简单的。但是在判断格子所处的状况时,两个改变  i  的语句相互冲突造成莫名其妙的错误,颇费了些时间。


#include<cstdio>#define _p(x,y) ((x)*L+y)char ct [20];int L,ans;int dx [12] = {-1,-2,-3,1,2,3, 0, 0, 0,0,0,0};//两个数组表示一个点可能的12种动作int dy [12] = { 0, 0, 0,0,0,0,-1,-2,-3,1,2,3};bool check (int loc)//参数loc:待判断点的一维位号{if(ct[loc]=='X') return 0;//如果格子里有墙,则不能放置碉堡int x=loc/L,y=loc%L;//把一维数组中的位号转化为二维坐标for(int i=0;i<12;i++){//模拟loc点可能的12种动作if(x+dx[i]<0||y+dy[i]<0||x+dx[i]>=L||y+dy[i]>=L) continue;//移动后的点不在网格内,不作处理if(ct[_p(x+dx[i],y+dy[i])]=='B') return 0;//移动路线上已有碉堡,返回假if(ct[_p(x+dx[i],y+dy[i])]=='X') i=(i/3+1)*3-1;//碰到了墙,不但要停止,而且其后面的位置也不能走了} //此处改变的i与i++相冲突return 1;//没有相冲突的碉堡,返回真}void dfs (int loc,int cnt)//loc:当前选择的位置cnt:已放置的碉堡数{if(loc==L*L){//检索完全部网格,判断碉堡数是否为最大if(cnt>ans) ans=cnt;return;}dfs(loc+1,cnt);//首先,不放碉堡,直接继续下一层递归if(check(loc)){//判断该位置能不能放置碉堡ct[loc]='B';dfs(loc+1,cnt+1);//能放置,放置后进行下一层递归ct[loc]='.';}}int main (){//freopen("in.txt","r",stdin);while(scanf("%d",&L)&&L!=0){for(int i=0;i<L*L;i++)scanf(" %c",ct+i);ans=0;//最大碉堡数初始化为0dfs(0,0);//搜索位置为0,碉堡数为0printf("%d\n",ans);}return 0;}


0 0