ch_6801 棋盘覆盖

喜欢而已 提交于 2019-12-03 03:00:50

http://noi-test.zzstep.com/contest/0x60%E3%80%8C%E5%9B%BE%E8%AE%BA%E3%80%8D%E4%BE%8B%E9%A2%98/6801%20%E6%A3%8B%E7%9B%98%E8%A6%86%E7%9B%96

6801 棋盘覆盖 0x60「图论」例题

描述

给定一个N行N列的棋盘,已知某些格子禁止放置。求最多能往棋盘上放多少块的长度为2、宽度为1的骨牌,骨牌的边界与格线重合(骨牌占用两个格子),并且任意两张骨牌都不重叠。N≤100。

输入格式

第一行为n,t(表示有t个删除的格子)
第二行到t+1行为x,y,分别表示删除格子所在的位置
x为第x行,y为第y列,行列编号从1开始。 

输出格式

一个数,即最多能放的骨牌数

样例输入

8 0

样例输出

32

二分图最大匹配版题
#include<iostream>
#include<cstdio>

#define ri register int
#define u int

namespace opt {

    inline u in() {
        u x(0),f(1);
        char s(getchar());
        while(s<'0'||s>'9') {
            if(s=='-') f=-1;
            s=getchar();
        }
        while(s>='0'&&s<='9') {
            x=(x<<1)+(x<<3)+s-'0';
            s=getchar();
        }
        return x*f;
    }

}

using opt::in;

#define NN 10005
#define MM 10005*4

#include<cstring>

namespace mainstay {

    u N,K;

    u h[NN],cnt;

    struct node {
        u to,next;
    } a[MM];

    inline void add(const u &x,const u &y) {
        a[++cnt].next=h[x],a[cnt].to=y,h[x]=cnt;
    }

    inline u calc(const u &x,const u &y) {
        return ((x-1)*N+y);
    }

    u vt[NN],mat[NN],b[NN][NN];

    u dfs(const u &x) {
        for(ri i(h[x]); i; i=a[i].next) {
            u _y(a[i].to);
            if(!vt[_y]) {
                vt[_y]=1;
                if(!mat[_y]||dfs(mat[_y])) {
                    mat[_y]=x;
                    return 1;
                }
            }
        }
        return 0;
    }

    inline void solve() {
        N=in(),K=in();
        for(ri i(1); i<=K; ++i) {
            u _a(in()),_b(in());
            b[_a][_b]=1;
        }
        for(ri i(1); i<=N; ++i) {
            for(ri j(1); j<=N; ++j) {
                if(!b[i][j]) {
                    if(j+1<=N&&!b[i][j+1]) {
                        add(calc(i,j),calc(i,j+1));
                        add(calc(i,j+1),calc(i,j));
                    }
                    if(i+1<=N&&!b[i+1][j]) {
                        add(calc(i,j),calc(i+1,j));
                        add(calc(i+1,j),calc(i,j));
                    }
                }
            }
        }
        u ans(0);
        for(ri i(1); i<=N; ++i) {
            for(ri j(1); j<=N; ++j) {
                std::memset(vt,0,sizeof(vt));
                u _x((i-1)*N+j);
                if(((i+j)&1)&&dfs(_x)) ++ans;
            }
        }
        printf("%d",ans);
    }

}

int main() {

    //freopen("x.txt","r",stdin);
    std::ios::sync_with_stdio(false);
    mainstay::solve();

}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!