CODEVS 2171 棋盘覆盖

2171 棋盘覆盖

给出一张nn(n<=100)的国际象棋棋盘,其中被删除了一些点,问可以使用多少12的多米诺骨牌进行掩盖。


错误日志: 直接在模板上调整 \(maxn\) 时没有在相应邻接表数组位置把数组大小调整为 \(maxn * maxn\)


Solution

经典的二分图匹配问题
\(1\) 要素: 每个点只能被一张骨牌覆盖
\(0\) 要素: 将棋盘黑白染色, 其对角线格子不可能被一张骨牌覆盖
染色方法: \(if(i + j) \% 2 == 0\) 染为白色

Code

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
#define LL long long
#define REP(i, x, y) for(int i = (x);i <= (y);i++)
using namespace std;
int RD(){
    int out = 0,flag = 1;char c = getchar();
    while(c < '0' || c >'9'){if(c == '-')flag = -1;c = getchar();}
    while(c >= '0' && c <= '9'){out = out * 10 + c - '0';c = getchar();}
    return flag * out;
    }
const int maxn = 419, maxv = 1000019, INF = 1e9 + 19;
int head[maxn * maxn],nume = 1;
struct Node{
    int v,dis,nxt;
    }E[maxv << 3];
void add(int u,int v,int dis){
    E[++nume].nxt = head[u];
    E[nume].v = v;
    E[nume].dis = dis;
    head[u] = nume;
    }
int len, num;
int map[maxn][maxn];
int mx[4] = {1,-1, 0, 0};
int my[4] = {0, 0, 1,-1};
bool judge(int x, int y){
    if(x < 1 || x > len || y < 1 || y > len)return 0;
    return 1;
    }
int id(int x, int y){return (x - 1) * len + y;}
int mat[maxn * maxn], used[maxn * maxn];
bool match(int u){
    for(int i = head[u];i;i = E[i].nxt){
        int v = E[i].v;
        if(!used[v]){
            used[v] = 1;
            if(!mat[v] || match(mat[v])){
                mat[v] = u;
                return 1;
                }
            }
        }
    return 0;
    }
int main(){
    len = RD(), num = RD();
    REP(i, 1, num){
        int x = RD(), y = RD();
        map[x][y] = 1;
        }
    REP(i, 1, len)REP(j ,1, len){
        if((i + j) % 2 == 1 || map[i][j])continue;
        int u = id(i ,j);
        for(int k = 0;k < 4;k++){
            int nx = i + mx[k];
            int ny = j + my[k];
            if(!judge(nx, ny))continue;
            if(map[nx][ny])continue;
            int v = id(nx, ny);
            add(u, v, 1);
            }
        }
    int ans = 0;
    REP(i, 1, len)REP(j, 1, len){
        if((i + j) % 2 == 1 || map[i][j])continue;
        memset(used, 0, sizeof(used));
        if(match(id(i, j)))ans++;
        }
    printf("%d\n", ans);
    return 0;
    }

转载于:https://www.cnblogs.com/Tony-Double-Sky/p/9755350.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值