标签:建图 scan strong 题意 cst ems stdin open stack
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; } }
标签:建图 scan strong 题意 cst ems stdin open stack
原文地址:https://www.cnblogs.com/jrfr/p/13552328.html