杭电1045————DFS简单难度题目

来源:互联网 发布:vue.js highcharts 编辑:程序博客网 时间:2024/06/14 17:14

Fire Net

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


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
这个题目很像八皇后,黑圆圈表示碉堡,同一行或者同一列不能有两个碉堡,除非他们之前有黑墙。
这个题目我一开的思路是这样的
读取地图完毕后
DFS(第一个可以放置碉堡的位置)
如果这一点放置碉堡,那么它的横向和纵向都不能在放置碉堡,我开了一个vis[x][y]数组记录下这种不能放置碉堡的状态..但是我回溯的时候傻眼了...加入说不能刚才试的那一点放置了碉堡之后不是最优解,我必须把之前vis[x][y]全部还原成之前的状态...那只能说太麻烦了。
而且还有一个问题,就是如果纵向或者横向碰到了墙的时候,该用代码去描述...于是我就纠结了一会啊...发现这个思路很难实现..
然后百度了一下看到了一种思路...立马就改了,其实是一道比较基础的DFS.
思路如下:
对map上的每一个点搜索。
搜索之前用一个函数canset()判断一下这个店是不是可以放置碉堡。
”可不可以放置碉堡“我想这个问题还是不算困难的...主要是通过这一点的坐标,向四个方向扩展,如果说这四个方向已经有过碉堡了,直接return false...代码实现起来较为简单。
DFS()中传递的参数就是放置第几个碉堡啦..每次canset()为true就调用DSF(碉堡数+1)之后就是简单的回溯..
附上代码,杭电亲测0MS
#include <cstdio>#include <cstring>#include <algorithm>#define maxn  4//1.什么时候搜索结束。//2.搜索的方式,即已知一个点怎么搜索啊../*这一个点的上下左右的所有街道(只要不碰到wall,vis应该全部置为1*/ int map[maxn][maxn];/*0是街道1是墙2是碉堡*/ int n,maxnum;void read(){char str[5];for(int i = 0 ; i < n ; i++){getchar();scanf("%s",str);for(int j = 0 ; j < n ; j++){if(str[j] == 'X')map[i][j] = 1;elsemap[i][j] = 0;}}}bool canset(int x,int y){int i,j;if(map[x][y] == 2 || map[x][y] == 1)return false;/*如果当前坐标已经放过碉堡或者是墙,直接returen false*//*下面就是朝四个方向扩展,判断是否可以放碉堡*/if(x < n)/*right扩展*/{for(i = x + 1 ; i < n ; i++)if(map[i][y] == 1) /*遇到了墙是还可以放碉堡的,退出循环待定*/break;else if(map[i][y] == 2)return false;}if(x > 0)/*left扩展*/{for(i = x - 1 ; i >= 0 ; i--)if(map[i][y] == 1) /*遇到了墙是还可以放碉堡的*/break;else if(map[i][y] == 2)return false;} if(y < n)/*up扩展*/{for(j = y + 1 ; j < n ; j++)if(map[x][j] == 1)break;else if(map[x][j] == 2)return false;} if(y > 0)/*down扩展*/{for(j = y - 1 ; j >=0 ; j--)if(map[x][j] == 1)break;else if(map[x][j] == 2)return false;} return true;}void DFS(int num)/**/ {if(num > maxnum)maxnum = num;for(int i = 0 ; i < n ; i++){for(int j = 0 ; j < n ; j++){if(canset(i,j))/*这个位置可以放置碉堡*/ {map[i][j] = 2;DFS(num+1);map[i][j] = 0;}}}}int main(){while(scanf("%d",&n) != EOF && n){memset(map,0,sizeof(map));read();maxnum= 0;DFS(0);printf("%d\n",maxnum);}return 0;}
经验教训:
我感觉ACM就像数学题一样..思路对了很容易很快做出来,思路不对再简单的题目也要卡很久(总结起来就是智商问题...otz)所以一定要先把思路理清楚啊!不要急着敲代码啊混蛋!!!
 
0 0