zoukankan      html  css  js  c++  java
  • poj 2226 Muddy Fields

    Muddy Fields
    Time Limit: 1000MS   Memory Limit: 65536K
    Total Submissions: 10807   Accepted: 4015

    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.
     
    题意:下雨之后农场某些土地泥泞了,牛不喜欢吃泥泞的草,约翰准备将这些泥泞的土地用宽度为1,长度不限的木板覆盖起来(木板只能平行于农场的长或宽来放置),问至少需要多少木板才可以把所有泥泞的土地都覆盖。
    思路:对于土地上每一个‘*’,找找横向需要哪块木板去覆盖,竖向又需要那块木板来覆盖。
    以题目为例:全是横向木板的放法:1 0 2 0数字是木板的编号,譬如‘333’就是一块木板,全是竖向木板:1 0 4 0
                                                            0 3 3 3                                                                                               0 3 4 5
                                                            4 4 4 0                                                                                               2 3 4 0
                                                            0 0 5 0                                                                                               0 0 4 0
    那么譬如第一行第二个‘*’的位置如果用横向木板,就用横向第二块木板来覆盖,或者竖向第4块来覆盖。即可连接这两块木板,如此操作可构成二分图,图中两边的点代表横向竖向的木板,连边则代表一块泥泞的‘*’,对于每一条边而言我们至少要取到这条边的其中一个顶点,并且要使得取到的这个顶点集合尽量的小,就是求最小顶点覆盖。
    AC代码:
    #define _CRT_SECURE_NO_DEPRECATE
    #include<iostream>
    #include<algorithm>
    #include<queue>
    #include<set>
    #include<vector>
    #include<cstring>
    #include<string>
    using namespace std;
    #define INF 0x3f3f3f3f
    const int N_MAX = 2500+100,R_MAX=50+5;
    int V;//点的个数
    vector<int>G[N_MAX];
    int match[N_MAX];
    bool used[N_MAX];
    void add_edge(int u, int v) {
        G[u].push_back(v);
        G[v].push_back(u);
    }
    
    bool dfs(int v) {
        used[v] = true;
        for (int i = 0; i < G[v].size(); i++) {
            int u = G[v][i], w = match[u];
            if (w < 0 || !used[w] && dfs(w)) {
                match[v] = u;
                match[u] = v;
                return true;
            }
        }
        return false;
    }
    
    int bipartite_matching() {
        int res = 0;
        memset(match, -1, sizeof(match));
        for (int v = 0; v < V; v++) {
            if (match[v] < 0) {
                memset(used, 0, sizeof(used));
                if (dfs(v))
                    res++;
            }
        }
        return res;
    }
    char field[N_MAX][N_MAX];
    int mark_x[N_MAX][N_MAX],mark_y[N_MAX][N_MAX];
    
    int R, C;
    int main() {
        while (scanf("%d%d",&R,&C)!=EOF) {
            memset(mark_x, -1, sizeof(mark_x));
            memset(mark_y, -1, sizeof(mark_y));
            for (int i = 0; i < R; i++){
                    char c;
                    scanf("%s",field[i]);
                }
            int num = 0; bool flag = 0,New=0;
            for (int i = 0; i < R;i++) {
                for (int j = 0; j < C;j++) {
                    if (field[i][j] == '*') {
                        num++;
                        while (j<C&&field[i][j]=='*') {
                            mark_x[i][j] = num;
                            j++;
                        }
                    }
                }
            }
    
    
             num = 0,flag=0, New = 0;
             for (int i = 0; i < C; i++) {
                 for (int j = 0; j < R; j++) {
                     if (field[j][i] == '*') {
                         num++;
                         while (j<R&&field[j][i] == '*') {
                             mark_y[j][i] = num;
                             j++;
                         }
                     }
                 }
             }
    
    
            V =N_MAX;
            //1~N_MAX/2:横向木板
            //N_MAX/2+1~N_MAX:纵向木板
            for (int i = 0; i < R; i++) {
                for (int j = 0; j < C; j++) {
                    if (field[i][j] == '*') {
                        add_edge(mark_x[i][j],mark_y[i][j]+N_MAX/2);
                    }
                }
        }
    
            printf("%d
    ",bipartite_matching());
            for (int i = 0; i < V;i++) {
                G[i].clear();
            }
        }
        return 0;
    }
  • 相关阅读:
    RecyclerView
    Android动态广播的注册与销毁
    使用FFmpeg让mp4转gif
    当你安装python3没有安装依赖环境yum install -y libffi-devel,pip和setuptools,pip会装不上,不安装yum -y install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel lib
    遇到的39.0或者其他版本不匹配的问题,请找对路径
    yaml创建学习(第二天)
    yaml 测试用例 (学习第一天)
    关于二次封装css selector 的复数定位
    uiautomatorviewer报错“Error taking device screenshot: EOF” ,
    appium解决每次运行都需要安装Unlock以及AppiumSetting的问题
  • 原文地址:https://www.cnblogs.com/ZefengYao/p/7266919.html
Copyright © 2011-2022 走看看