zoukankan      html  css  js  c++  java
  • poj2226

    题意:给定一个矩阵,其中有一些地方有水,用一些长度任意,宽度为1的木板盖住这些有水的地方,问至少需要几块板子。

    分析:二分图最小点集覆盖。二分图建图方法如下,把每段连续的横向的水洼看成是一个X集合中的点,每段连续的纵向的水洼看成是Y集合中的点。矩阵每个有水单元看成是一个边,它连接了它所在的横向水洼在X集合中对应的点和它所在的纵向水洼在Y集合中对应的点。(对于一段连续的水洼,如果要铺木板,一定要铺得尽量长)这样最小点集覆盖的意义就变成了,矩阵中的每个有水的单元(二分图中的每条边)所在的横向和纵向的水洼(在X集合和Y集合中的两个端点)至少有一个被覆盖。求至少需要选几个点。

    View Code
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    using namespace std;
    
    #define maxr 55
    #define maxc 55
    #define maxx maxr * maxc / 2
    #define maxy maxx
    
    struct Edge
    {
        int x, y;
    }edge[maxr][maxc];
    
    int row, column;
    char map[maxr][maxc];
    int xcount, ycount;
    bool visit[maxy];
    int match[maxy];
    bool g[maxx][maxy];
    
    void input()
    {
        scanf("%d%d", &row, &column);
        for (int i = 0; i < row; i++)
            scanf("%s", map[i]);
    }
    
    void make()
    {
        xcount = 0;
        ycount = 0;
        for (int i = 0; i < row; i++)
        {
            int j = 0;
            while (j < column)
            {
                while (j < column && map[i][j] == '.')
                    j++;
                if (j >= column)
                    break;
                while (j < column && map[i][j] == '*')
                {
                    edge[i][j].x = xcount;
                    j++;
                }
                xcount++;
            }
        }
    
        for (int i = 0; i < column; i++)
        {
            int j = 0;
            while (j < row)
            {
                while (j < row && map[j][i] == '.')
                    j++;
                if (j >= row)
                    break;
                while (j < row && map[j][i] == '*')
                {
                    edge[j][i].y = ycount;
                    j++;
                }
                ycount++;
            }
        }
    
        for (int i = 0; i < row; i++)
            for (int j = 0; j < column; j++)
                if (map[i][j] == '*')
                {
                    //printf("%d %d\n", edge[i][j].x, edge[i][j].y);
                    g[edge[i][j].x][edge[i][j].y] = true;
                }
    }
    
    bool dfs(int k)
    {
        int t;
        for (int i = 0; i < ycount; i++)
        {
            if (g[k][i] && !visit[i])
            {
                visit[i] = true;
                t = match[i];
                match[i] = k;
                if (t == -1 || dfs(t))
                    return true;
                match[i] = t;
            }
        }
        return false;
    }
    
    int max_match()
    {
        int ans = 0;
        for (int i = 0; i < xcount; i++)
        {
            memset(visit, false, sizeof(visit));
            if (dfs(i))
                ans ++;
        }
        return ans;
    }
    
    int main()
    {
        //freopen("t.txt", "r", stdin);
        memset(g, 0, sizeof(g));
        input();
        make();
        memset(match, -1, sizeof(match));
        printf("%d\n", max_match());
        return 0;
    }
  • 相关阅读:
    表、栈和队列
    POJ 1207 The 3n + 1 problem
    记录一个很低级的错误:command 'usr/local/cuda/bin/vncc' failed with exit status 2
    [转载]Benchmark和baseline的区别
    [转载]神经网络架构搜索(Neural Architecture Search)杂谈
    CNN常用图片分类网络
    [转载]OCR原理
    目标检测、实例分割学习
    [转载]上采样
    自动驾驶资料收集
  • 原文地址:https://www.cnblogs.com/rainydays/p/2575794.html
Copyright © 2011-2022 走看看