zoukankan      html  css  js  c++  java
  • hdu 1045

    Fire Net

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


    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..
    ....
    2
    XX
    .X
    3
    .X.
    X.X
    .X.
    3
    ...
    .XX
    .XX
    4
    ....
    ....
    ....
    ....
    0
     
    Sample Output
    5 1 5 2 4
     
    Source
     
    Recommend
    We have carefully selected several similar problems for you:  1016 1051 1010 1050 1175 
     本题的题意时有若干个强,求最多可以安装多少个炮台,可以保证连续的行或则列不会出现两个大炮,除非是中间有面墙隔着,
    可以用二分图解决,此题和poj一道也是求最短路劲的提类似,那个题也是用二分图解决的,
    至于具体的思想希望大家好好理解二分图的含义吧,这个题字面上是无法解释清楚的
    下面附上代码
    #include<stdio.h>
    #include<string.h>
    #include<queue>
    #include<algorithm>
    #include<iostream>
    using namespace std;
    const int maxn =100;
    const int INF = 1000000000;
    bool vis[maxn];     //查询右集合中的点有没有被访问过
    int link[maxn];     //link[i]表示右集合中的i点是由左集合中的哪个点连接的
    int G[maxn][maxn];     //邻接矩阵
    int x_cnt;
    int y_cnt;            //左右集合的点的个数
    char map[10];
    int mapr[10][10];
    int mapl[10][10];
    
    bool find(int u){         //用来寻找增广路
        for(int i = 1; i <= y_cnt; i++){   //遍历右集合中的每个点
            if(!vis[i] && G[u][i]){    //没有被访问过并且和u点有边相连
                vis[i] = true;  //标记该点
                if(link[i] == -1 || find(link[i])){
                    //该点是增广路的末端或者是通过这个点可以找到一条增广路
                    link[i] = u;//更新增广路   奇偶倒置
                    return true;//表示找到一条增广路
                }
            }
        }
        return false;//如果查找了右集合里的所有点还没找到通过该点出发的增广路,该点变不存在增广路
    }
    
    int solve(){
        int num = 0;
        memset(link, -1, sizeof(link));//初始化为-1表示  不与左集合中的任何元素有link
        for(int i = 1; i <= x_cnt; i++){  //遍历左集合
            memset(vis, false, sizeof(vis));//每一次都需要清除标记
            if(find(i))
                num++;//找到一条增广路便num++
        }
        return num;
    }
    int main(){
        int n;
        while(scanf("%d",&n)!=EOF){
            if(n==0)
            break;
            memset(G,0,sizeof(G));
            memset(map,0,sizeof(map));
            memset(mapr,0,sizeof(mapr));
            memset(mapl,0,sizeof(mapl));
    
           for(int i=1;i<=n;i++){
               scanf("%s",map+1);
               getchar();
               for(int j=1;j<=n;j++){
                   if(map[j]=='X'){
                        mapr[i][j]=mapl[i][j]=-1;
                   }
               }
           }
           x_cnt=0;
            y_cnt=0;
           for(int i=1;i<=n;i++){
               for(int j=1;j<=n;j++){
                   while(mapr[i][j]==-1&&j<=n)
                        j++;
                    x_cnt++;
                   while(mapr[i][j]==0&&j<=n){
                       mapr[i][j]=x_cnt;
                       j++;
                   }
               }
           }
            
          for(int j=1;j<=n;j++){
             for(int i=1;i<=n;i++){
                  while(mapl[i][j]==-1&&i<=n)
                        i++;
                    y_cnt++;
                   while(mapl[i][j]==0&&i<=n){
                       mapl[i][j]=y_cnt;
                       i++;
                   }
             }
          }
    
            for(int i=1;i<=n;i++){
               for(int j=1;j<=n;j++){
                   if(mapr[i][j]!=-1&&mapl[i][j]!=-1)
                   G[mapr[i][j]][mapl[i][j]]=1;
               }
            }
    
            printf("%d
    ",solve());
        }
        return 0;
    }
  • 相关阅读:
    虚拟机LUN扩大后,重新分区
    rm: cannot remove `/home/cn0000/log/formlog.20140417': Read-only file system
    sybase 备份和恢复
    全表扫描计算成本
    标量子查询 子查询执行次数计算公式
    left join 关联条件位置
    动态SQL使用绑定变量
    如何在SQLServer中处理每天四亿三千万记录的
    移动端UI一致性解决方案
    工业互联网中MES系统的重要性
  • 原文地址:https://www.cnblogs.com/13224ACMer/p/4795713.html
Copyright © 2011-2022 走看看