• 8、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 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.

    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.

    Sample input:

    4
    .X..
    ....
    XX..
    ....
    2
    XX
    .X
    3
    .X.
    X.X
    .X.
    3
    ...
    .XX
    .XX
    4
    ....
    ....
    ....
    ....
    0
    

    Sample output:

    5
    1
    5
    2
    4
     
    解题思路:对于这道题,其实我真的没什么完整的思路,在这里要特别感谢博主 @小媛在努力
    我只是按照她的思路用Java实现了,其实大同小异。下面我说一下我的理解:
    本题旨在寻找最多数目的blockhouses,可以放置blockhouse的位置分为两种:其一为同行同列没有与其相连的blockhouse(相连不是相邻),其二为有fire net与其相连;这两种位置可以相互重叠,只要保证不出现两个blockhouse可以被一条横或竖线直接连接而不经过任何障碍。
    代码主要有两个部分,第一个函数为检查每一个位置的上下左右,0代表什么都没有,1代表可以放置blockhouse,2代表fire net;第二个函数为DFS(深度优先遍历算法),这个算法的思想大致为从图的第一个顶点出发,按照深度方向搜索,实现对图中所有顶点访问且只访问一次。具体用在本题就是:从第一个位置出发,找寻所有可以放置的blockuse,之后从倒数第二个放置的blockhouse开始,看有无更多的可能性,完了之后再从倒数第三个开始,以此类推,直到返回到第一个放置的blockhouse后,从它的下一个位置开始重复上述过程。
    具体代码:
     1 import java.util.*;
     2 public class Main {
     3      static int [][] traverse=new int[10][10];
     4      static int n,cout,maxNum;
     5      public static int sign(int x,int y) {
     6           for(int i=y;i>=0;i--){
     7               if(traverse[x][i]==1)
     8                    return 0;
     9               if(traverse[x][i]==2)
    10                    break;
    11           }
    12         for(int i=y;i<n;i++){
    13           if(traverse[x][i]==1)
    14                    return 0;
    15               if(traverse[x][i]==2)
    16                    break;
    17           }
    18         for(int i=x;i>=0;i--){
    19           if(traverse[i][y]==1)
    20                    return 0;
    21               if(traverse[i][y]==2)
    22                    break;
    23           }
    24         for(int i=x;i<n;i++){
    25           if(traverse[i][y]==1)
    26                    return 0;
    27               if(traverse[i][y]==2)
    28                    break;
    29           }
    30           return 1;
    31      }
    32 
    33      public static void dfs() {
    34           if(cout>maxNum){
    35               maxNum=cout;
    36           }
    37           for(int k=0;k<n;k++){
    38               for(int j=0;j<n;j++){
    39                    if(traverse[k][j]==0&&sign(k, j)==1){
    40                         traverse[k][j]=1;
    41                         cout++;
    42                         dfs();
    43                         traverse[k][j]=0;
    44                         cout--;
    45                    }
    46               }
    47           }
    48      }
    49      public static void main(String[] args) {
    50          String city;
    51          char[] cityStr=new char[10];
    52           Scanner scanner=new Scanner(System.in);
    53           while((n=scanner.nextInt())!=0){
    54               maxNum=cout=0;
    55               for(int i=0;i<n;i++){
    56                    city=scanner.next();
    57                    cityStr=city.toCharArray();
    58                    for(int m=0;m<n;m++){
    59                         traverse[i][m]=(cityStr[m]=='X'?2:0);
    60                    }
    61               }
    62               dfs();
    63               System.out.println(maxNum);
    64           }
    65      }
    66 }
    做题感悟1、大部分常见OJ要求只能提交一个源代码段落,即只能有一个.java文件。通常文件命名为Main,程序入口为public static void main().
    而Java要求public的类必须与所在文件同名。因此只能是
    public class Main{
        public static void main(String [] args){
        }
    }
    当另外构建class时,不能再使用public关键词。
    使用java.util.Scanner或Reader等类封装System.in时,注意只能有一个封装实例,否则可能弄丢输入数据。
    2、这是在ZOJ上做的第一道题,感觉到了深深的恶意,上一道是A+B,下一道直接上这个,不过这样才能让自己有所提高。
    3、一定要好好学数据结构,不管是为了考研还是编程能力,都急需。
  • 相关阅读:
    UVa 727
    UVa 11495
    UVa 299
    UVa 10194
    UVa 146
    10025
    Tug of War POJ 2576 DP(类似背包)
    Problem A: Freckles UVA 10034 裸生成树
    UVA 562
    CF DIV 2 206 C. Vasya and Robot
  • 原文地址:https://www.cnblogs.com/langzi1996/p/6440802.html
Copyright © 2020-2023  润新知