链接:https://vjudge.net/problem/POJ-2446#author=0
题意:
有一天,罗老板画了一块尺寸为M * N的棋盘。他希望许老师能够使用1 * 2的牌来覆盖棋盘。然而,他认为这很容易,所以他增大了难度,他在棋盘上打了一些洞
许老师必须遵守以下规则:
1.任何不是洞网格都应该只被一张卡覆盖。
2. 一张卡应该正好覆盖2个相邻非洞网格。
3. 洞不可以被卡片覆盖
你的任务是帮助许老师确定 根据上述规则 是否存在一种方案可以覆盖棋盘
思路:
二分图匹配.因为一个1*2的方块,所放的两个格子,一个格子的x+y是偶数,一个是奇数,所以可以以x+y根据奇偶建图,再去求二分图。
代码:
#include <iostream> #include <memory.h> #include <string> #include <istream> #include <sstream> #include <vector> #include <stack> #include <algorithm> #include <map> #include <queue> #include <math.h> #include <cstdio> #include <set> #include <iterator> #include <cstring> using namespace std; typedef long long LL; const int MAXN = 2000; int Next[4][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; int Dis[40][40]; int G[MAXN][MAXN]; int Link[MAXN]; bool Used[MAXN]; int n, m, k; int cnt1, cnt2; bool Dfs(int x) { for (int node = 1;node <= cnt2;node++) { if (G[x][node] == 1 && Used[node] == false) { Used[node] = true; if (Link[node] == -1 || Dfs(Link[node])) { Link[node] = x; return true; } } } return false; } int Solve() { int res = 0; memset(Link, -1, sizeof(Link)); for (int i = 1;i <= cnt1;i++) { memset(Used, 0, sizeof(Used)); if (Dfs(i)) res++; } return res; } int main() { while (cin >> n >> m >> k) { memset(Dis, 0, sizeof(Dis)); int y, x; for (int i = 1;i <= k;i++) { cin >> y >> x; Dis[x][y] = -1; } cnt1 = cnt2 = 0; for (int i = 1;i <= n;i++) { for (int j = 1;j <= m;j++) { if (Dis[i][j] != -1) { if ((i+j)%2 == 0) Dis[i][j] = ++cnt1; else Dis[i][j] = ++cnt2; } } } for (int i = 1;i <= n;i++) { for (int j = 1;j <= m;j++) { if (Dis[i][j] != -1 && (i+j)%2 == 0) { for (int k = 0;k < 4;k++) { int tx = i+Next[k][0]; int ty = j+Next[k][1]; if (tx < 1 || tx > n || ty < 1 || ty > m) continue; G[Dis[i][j]][Dis[tx][ty]] = 1; } } } } if ((n*m-k)%2 == 1 || cnt1 != cnt2) { cout << "NO" << endl; continue; } int res = Solve(); if (res == (n*m-k)/2) cout << "YES" << endl; else cout << "NO" << endl; } return 0; }
原文地址:https://www.cnblogs.com/YDDDD/p/10859069.html
时间: 2024-10-10 10:02:11