zoukankan      html  css  js  c++  java
  • 多米诺(codevs 3052)

    题目描述 Description

    一个矩形可以划分成M*N个小正方形,其中有一些小正方形不能使用。一个多米诺骨牌占用两个相邻的小正方形。试问整个区域内最多可以不重叠地放多少个多米诺骨牌且不占用任何一个被标记为无法使用的小正方形。

    输入描述 Input Description

    第一行有两个用空格隔开的正整数M和N。

        第二行有一个正整数K,表示共有K个小正方形不能使用。输入数据保证K<=M*N。

        以下K行每行有两个用空格隔开的数X和Y,表示第X行的第Y个小正方形不能使用。

    输出描述 Output Description

    输出最多能放多少个多米诺骨牌。

    样例输入 Sample Input

    3 3

    2

    1 1

    2 2

    样例输出 Sample Output

    3

    数据范围及提示 Data Size & Hint

    对于30%的数据,M=1;

        对于50%的数据,M<=2;

        对于70%的数据,M<=3;

        对于100%的数据,M<=50,N<=50。

    /*
      二分图匹配问题
      问题是从一坨方格关系中选出尽量多的关系,使每个方格只选一次。 
      通过观察我们可以发现,横坐标加纵坐标是偶数的方格只能和奇数的方格匹配,所以就变成了二分图的匹配问题。 
    */
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #define N 51
    using namespace std;
    int g[N][N],n,m,p,head[N*N],cnt;
    int used[N*N],belong[N*N];
    struct node{
        int v,pre;
    };node e[N*N*2];
    void add(int x,int y){
        e[++cnt].v=y;
        e[cnt].pre=head[x];
        head[x]=cnt;
    }
    bool find(int i){
        for(int j=head[i];j;j=e[j].pre){
            if(!used[e[j].v]){
                used[e[j].v]=1;
                if(!belong[e[j].v]||find(belong[e[j].v])){
                    belong[e[j].v]=i;
                    return true;
                }
            }
        }
        return false;
    }
    int main(){
        freopen("jh.in","r",stdin);
        scanf("%d%d%d",&n,&m,&p);
        for(int i=1;i<=p;i++){
            int x,y;scanf("%d%d",&x,&y);
            g[x][y]=1;
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                if((i+j&1)||g[i][j])continue;
                if(!g[i-1][j]&&i-1>=1)add((i-1)*m+j,(i-2)*m+j);
                if(!g[i+1][j]&&i+1<=n)add((i-1)*m+j,i*m+j);
                if(!g[i][j-1]&&j-1>=1)add((i-1)*m+j,(i-1)*m+j-1);
                if(!g[i][j+1]&&j+1<=m)add((i-1)*m+j,(i-1)*m+j+1);
            }
        }
        int tot=0;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                if((i+j&1)||g[i][j])continue;
                memset(used,0,sizeof(used));
                if(find((i-1)*m+j))tot++;
            }
        }
        printf("%d",tot);
        return 0;
    }
  • 相关阅读:
    数仓1.3 |行为数据| 业务数据需求
    数仓1.1 |概述| 集群环境搭建
    麒麟Kylin
    ng--todolist
    mysql必知必会--用正则表达式 进行搜索
    mysql必知必会--用通配符进行过滤
    mysql必知必会--数 据 过 滤
    mysql必知必会--过 滤 数 据
    mysql必知必会--排序检索数据
    mysql必知必会--检 索 数 据
  • 原文地址:https://www.cnblogs.com/harden/p/6052588.html
Copyright © 2011-2022 走看看