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;
	}
posted @ 2018-10-08 16:49  Tony_Double_Sky  阅读(184)  评论(0编辑  收藏  举报