• HDU 1045 Fire Net 【二分图匹配】


    <题目链接>

    题目大意:

    题意思是给出一张图,图中'X'表示wall,'.'表示空地,可以放置炮台,同一条直线上只能有一个炮台,除非有'X'隔开,问在给出的图中最多能放置多少个炮台。

    解题分析:

    本题可用DFS求解 >>> ,但是二分匹配的想法更加巧妙,效率也更高。二分匹配的主要思想就是,对矩阵的行连通块和列连通块进行标号,然后根据矩阵的每个点,建立对应的行连通块和列连通块之间的匹配关系,然后利用匈牙利进行正式匹配,这样当某个行联通块与某个列连通块正式确立匹配关系的时候,说明这两个连通块的交点坐标(之一)放碉堡,而它们的其它部分则不能放碉堡。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 using namespace std;
     6 int nrow,ncol;
     7 int g[20][20],linker[20];
     8 bool used[20];
     9 char map[5][5];
    10 int maprow[5][5],mapcol[5][5];
    11 bool dfs(int u){
    12     for(int v=1;v<=ncol;v++)
    13         if(g[u][v]&&!used[v]){
    14             used[v]=true;
    15             if(!linker[v]||dfs(linker[v])){
    16                 linker[v]=u;
    17                 return true;
    18             }    
    19         } 
    20     return false;   
    21 }  
    22 int Hungary(){
    23     int res=0;
    24     memset(linker,0,sizeof(linker));     //将行连通块的归属全部置为空
    25     for(int u=1;u<=nrow;u++){
    26         memset(used,0,sizeof(used));
    27         if(dfs(u))res++;
    28     }   
    29     return res; 
    30 }  
    31 int main(){
    32     int i,j,n;
    33     while(scanf("%d",&n),n){
    34         memset(mapcol,0,sizeof(mapcol));
    35         memset(maprow,0,sizeof(maprow));
    36         memset(g,0,sizeof(g));
    37         for(i=1;i<=n;i++){
    38             for(j=1;j<=n;j++){
    39                 cin>>map[i][j];
    40                 if(map[i][j]=='X')
    41                    mapcol[i][j]=maprow[i][j]=-1;    //X点的行连通编号和列连通编号均标为-1
    42             }  
    43         }
    44         int p1=0;
    45         nrow=0;ncol=0;
    46         //给行编号 
    47         for(i=1;i<=n;i++){
    48             for(j=1;j<=n;j++){              
    49                 while(maprow[i][j]==-1&&j<=n)     //跳过这一行的X部分
    50                     j++;
    51                 p1++;   //p1代表序号
    52                 while(maprow[i][j]!=-1&&j<=n){
    53                       maprow[i][j]=p1;     //给第i行连续的连通块打上相同标号p1  
    54                       if(nrow<p1) nrow=p1;  //记录所有行中,行联通块的最大编号
    55                       j++;
    56                 } 
    57             }
    58         }
    59         int p2=0;
    60         //给列编号 
    61         for(j=1;j<=n;j++)
    62             for(i=1;i<=n;i++){
    63                 while(mapcol[i][j]==-1&&i<=n)    //遍历第j列的时候,跳过X部分
    64                     i++;
    65                 p2++;    
    66                 while(mapcol[i][j]!=-1&&i<=n){
    67                     mapcol[i][j]=p2;    //给第j列的连续的联通块标上相同的序号
    68                     if(ncol<p2)ncol=p2;   //记录下所有列中,列连通块的最大标号
    69                     i++;
    70                 }    
    71             }
    72         for(i=1;i<=n;i++)
    73             for(j=1;j<=n;j++){
    74                 if(maprow[i][j]!=-1&&mapcol[i][j]!=-1)
    75                     g[maprow[i][j]][mapcol[i][j]]=1;     //将每个空格点的行连通标号与列连通标号 构建匹配关系
    76             }
    77         printf("%d
    ",Hungary());            
    78     } 
    79     return 0;   
    80 }

     2018-11-10

  • 相关阅读:
    如何制作URL文件
    对象映射工具AutoMapper介绍
    C#高阶函数介绍
    System.Web.Caching.Cache
    系统架构设计:进程缓存和缓存服务,如何抉择?
    System.Web.Caching.Cache类 缓存 各种缓存依赖
    max server memory (MB)最大服务器内存配置--缓解内存压力
    第0节:.Net版基于WebSocket的聊天室样例
    第六节:Core SignalR中的重连机制和心跳监测机制详解
    第五节:SignalR完结篇之依赖注入和分布式部署
  • 原文地址:https://www.cnblogs.com/00isok/p/9940789.html
Copyright © 2020-2023  润新知