HDU:Fire Net

来源:互联网 发布:奇葩说肖骁 知乎 编辑:程序博客网 时间:2024/06/05 17:24

Fire Net

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

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. 

假设我们有一个有着直直的街道的方形的城市,方形城市的地图是NN列,

每一个代表一条街道或一道墙。


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
5
1
5
2
4

大致题意:

给定一些空地和堡垒,在其中可放上最多的机枪。如果没有堡垒阻挡的话,机枪不能在同一横线和竖线上,不然的机枪会扫射到其他

机枪。其中X代表堡垒,.代表空地。解题思路:用深搜,从左向右,从上到下进行搜索,没搜索一个位置,先看看这个位置是不是点

,如果是点才可以放枪,然后我们要判断该点是否合法,如果该点左边或上边在遇到墙之前都没有枪,或根本没有枪,那么这一点就

是合法的,则我们放枪将这个位置标记,然后继续进行搜索,让枪数加1,让位置往后移一位,若当前位置不是合法的,则继续搜索下

一个位置,枪数不变,直到搜索到最后一个位置,让当前统计的枪数与当前枪数最大值进行比较,如果当前统计的枪数比最大枪数大

,则刷新可放置的最大枪数。最终输出可放置的最大枪数即可。

代码如下:

#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
char cmap[5][5]; //定义一个5*5的二位字符数组
int max_shotnum; //可放置的最大枪数
int n,i,j,k=0,pernum=0; //n为空地规模,i,j为循环变量,k是当前搜索的位置,pernum是当前已放置的枪的数量。
bool legal_or_not(int x,int y)  //判断点的坐标是否合法
{
//注意:之所以用下面方法判断是因为我们放置机枪的时候采用的是先以从左向右放,在从上向下放
    for(i=x-1;i>=0;i--) //我要将为枪的地方置为字符0
    {
        if(cmap[i][y]=='0')   //如果左边有枪而且没有墙阻挡,则该点不合法,不可以放置枪
            return false;
        if(cmap[i][y]=='X')   //只要一遇到墙该点必定合法
            break;
    }
    for(j=y-1;j>=0;j--) 
    {
        if(cmap[x][j]=='0') //如果上边有机枪而且没有墙阻挡,则该点不合法,不可以放枪
            return false;
        if(cmap[x][j]=='X') //只要一遇到墙则该点必定合法
            break;
    }
    return true;
}
void dfs(int k,int pernum) //深搜,k是当前搜索的位置,pernum是当前已放置的枪数
{
    int x,y; //横纵坐标x,y均由k确定
    x=k/n;
    y=k%n;
    if(k==n*n) //如果k是方格总数,则此次搜索完成
    {
        if(pernum>max_shotnum) //如果当前已放置的枪数比当前最大枪数大
            max_shotnum=pernum; //则当前最大枪数被刷新
        return; //返回
    }
    else
    {
        if(cmap[x][y]=='.'&&legal_or_not(x,y)) //如果这个地方是一个点且判断它的位置是合法的
        {
            cmap[x][y]='0'; //先将这个位置赋值为字符‘0’,代表这个位置已将有枪
            dfs(k+1,pernum+1); //搜索下一个位置,枪数+1
            cmap[x][y]='.';
        }
        dfs(k+1,pernum); //如果这个位置不合法,搜索下一个位置,枪数不变。
    }
}
int main()
{
    while(~scanf("%d",&n))
    {
        max_shotnum=0;
        if(n==0)
            break;
        for(i=0;i<n;i++)
        {
            scanf("%s",cmap[i]);
        }
        dfs(0,0);
        printf("%d\n",max_shotnum);
    }
    return 0;
}


0 0