1. 程式人生 > 實用技巧 >HDU 1045 最大匹配

HDU 1045 最大匹配

xg

題意

  給了一個4*4矩陣。圖中有的點代表山。要求在這個矩陣上放碉堡,碉堡可以上下,左右攻擊所能看到的碉堡,山可以阻擋兩邊碉堡互相看到,且碉堡不能放到山上。問最多可以放多少個碉堡。

思路

  資料範圍小可以暴力。

  但是用最大匹配解:

  在矩陣上的最大匹配問題,可以轉化為x,y座標的最大匹配。

  因為碉堡能進行格擋,則可以把x,y行問題轉化為一塊一塊。

  

  上圖是x座標的塊,然後和y的塊建圖最大匹配即可。

#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstring>
#include 
<string> #include <map> #include <iomanip> #include <algorithm> #include <queue> #include <stack> #include <set> #include <vector> #define bug cout<<"--------------"<<endl #define sp ' ' using namespace std; typedef long long ll; const int
maxn = 100; int n; int a[maxn][maxn]; int tot = 0; int head[maxn],ver[maxn],edge[maxn],nextt[maxn]; void add(int x,int y) { ver[++tot] = y,nextt[tot] = head[x] , head[x] = tot; } int match[maxn],vis[maxn]; bool dfs(int x) { for(int i = head[x],y;i; i = nextt[i]){ if(!vis[y = ver[i]]){ vis[y]
= 1; if(!match[y] || dfs(match[y])){ match[y] = x; return 1; } } } return 0; } int main() { //freopen("input.txt", "r", stdin); while(scanf("%d",&n) != EOF){ if(n == 0) break; int cnt = 0; memset(a,0,sizeof(a)); memset(head,0,sizeof(head)); memset(match,0,sizeof(match)); tot = 0; for(int i = 1; i<=n;++i){ for(int j=1;j<=n;++j){ char c; cin>>c; if(c == '.') a[i][j] = 1; } } for(int i = 1;i<=n;++i){ for(int j = 1;j <=n;++j){ if(a[i][j]){ if(a[i][j-1] == 0) cnt++; a[i][j] = cnt; } } } int nub = cnt; for(int j = 1;j <=n;++j){ for(int i = 1;i<=n;++i){ if(a[i][j]){ if(a[i-1][j] == 0) cnt++; add(a[i][j],cnt); //add(cnt,a[i][j]); } } } int ans = 0; for(int i = 1;i <= nub;++i){ memset(vis,0,sizeof(vis)); if(dfs(i)) ans++; } printf("%d\n",ans ); //bug; } }