zoukankan      html  css  js  c++  java
  • poj 2226 Muddy Fields(二分图最小点覆盖)

    B - Muddy Fields
    Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u

    Description

    Rain has pummeled the cows' field, a rectangular grid of R rows and C columns (1 <= R <= 50, 1 <= C <= 50). While good for the grass, the rain makes some patches of bare earth quite muddy. The cows, being meticulous grazers, don't want to get their hooves dirty while they eat. 

    To prevent those muddy hooves, Farmer John will place a number of wooden boards over the muddy parts of the cows' field. Each of the boards is 1 unit wide, and can be any length long. Each board must be aligned parallel to one of the sides of the field. 

    Farmer John wishes to minimize the number of boards needed to cover the muddy spots, some of which might require more than one board to cover. The boards may not cover any grass and deprive the cows of grazing area but they can overlap each other. 

    Compute the minimum number of boards FJ requires to cover all the mud in the field.

    Input

    * Line 1: Two space-separated integers: R and C 

    * Lines 2..R+1: Each line contains a string of C characters, with '*' representing a muddy patch, and '.' representing a grassy patch. No spaces are present.

    Output

    * Line 1: A single integer representing the number of boards FJ needs.

    Sample Input

    4 4
    *.*.
    .***
    ***.
    ..*.
    

    Sample Output

    4
    

    Hint

    OUTPUT DETAILS: 

    Boards 1, 2, 3 and 4 are placed as follows: 
    1.2. 
    .333 
    444. 
    ..2. 
    Board 2 overlaps boards 3 and 4.
     
    题意:给一张地图,其中有的点有水洼,要用木板把它们覆盖,求最小的木板数量(横着或者纵向)。
    思路:

    二分图中,选取最少的点数,使这些点和所有的边都有关联(把所有的边的覆盖),叫做最小点覆盖。
    把每段连续的横水洼看成集合A中的点,每段连续的纵水洼看成集合B中的点,中间的交点看成连线,
    因为每个有水单元必须覆盖,所以所连的2个单元至少有一个被覆盖。
    所以求最小点覆盖。思路很巧妙。

    而最小点覆盖 = 最大匹配数

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #include <string>
     5 #include <queue>
     6 #include <cstring>
     7 #include <vector>
     8 using namespace std;
     9 #define maxn 510 
    10 int R, C;
    11 int h[maxn][maxn], z[maxn][maxn];
    12 char mp[55][55];
    13 int line[maxn], vis[maxn];
    14 int cnth, cntz, ans;
    15 vector <int> q[maxn];
    16 void init(){
    17     memset(h, 0, sizeof(h));
    18     memset(z, 0, sizeof(z));
    19     memset(q, 0, sizeof(q));
    20     cnth = 1;
    21     for(int i = 1; i <= R; i++){
    22         for(int j = 1; j <= C; j++){
    23             if(mp[i][j] == '*') h[i][j] = cnth;
    24             if(mp[i][j] == '*' && mp[i][j+1] != '*') cnth++;
    25             
    26         }
    27     }
    28     
    29     cntz = 1;
    30     for(int i = 1; i <= C; i++){
    31         for(int j = 1; j <= R; j++){
    32             if(mp[j][i] == '*') z[j][i] = cntz;
    33             if(mp[j][i] == '*' && mp[j+1][i] != '*') cntz++;
    34         }
    35     }
    36     
    37     for(int i = 1; i <= R; i++){
    38         for(int j = 1; j <= C; j++){
    39             if(mp[i][j] == '*'){
    40                 q[h[i][j]].push_back(z[i][j]);
    41             }
    42         }
    43     }
    44 }
    45 bool find(int x){
    46     for(int i = 0; i < q[x].size(); i++){
    47         if(!vis[ q[x][i] ] ){
    48             vis[ q[x][i] ] = 1;
    49             if(!line[q[x][i]] || find(line[q[x][i]])){
    50                 line[q[x][i]] = x;
    51                 return true;
    52             }
    53         }
    54     }
    55     return false;
    56 }
    57 void hungry(){
    58     ans = 0;
    59     memset(line, 0, sizeof(line));
    60     for(int i = 1; i < 510; i++){
    61         memset(vis, 0, sizeof(vis));
    62         if(find(i)) ans++;
    63     }
    64     printf("%d
    ", ans);
    65     
    66 }
    67 int main(){
    68     while(~scanf("%d%d", &R, &C)){
    69         memset(mp, '-1', sizeof(mp));
    70         for(int i = 1; i <= R; i++){
    71             for(int j = 1; j <= C; j++) cin>>mp[i][j];
    72         }
    73         init();
    74         hungry();
    75     }
    76 
    77 
    78     return 0;
    79 }
  • 相关阅读:
    英语中的一个月几天的表示法
    深圳梧桐山游记
    linux中创建文件和文件夹
    linux中~和/的区别
    linux中的--和-的区别
    linux中vi和vim的区别
    基本数据类型大小和范围
    洛谷 [AHOI2001]质数和分解
    codevs 1115 开心的金明--01背包
    codevs 1080 线段树练习--用树状数组做的
  • 原文地址:https://www.cnblogs.com/titicia/p/3905864.html
Copyright © 2011-2022 走看看