要用1×2的板子尽量多的覆盖##区域,且不能交叉,求至多可以覆盖多少板子。
每一个#向向下或向右相邻的#建边。求最大匹配就可以了。
其实这题数据是比较弱的把,应该是#的个数在600以内把。。
#include <iostream> #include <cstdlib> #include <cstring> #include <string> #include <cstdio> #include <cmath> #include <algorithm> #include <vector> #include <queue> #include <map> #define inf 0x3f3f3f3f #pragma comment(linker, "/STACK:16777216") #define eps 1e-6 #define ll long long using namespace std; int n,cnt,mx[605],my[605],vis[605],e[605][605],mp[605][605]; char s[605][605]; int path(int i) { int j; for(j=1;j<cnt;j++) { if(e[i][j]&&!vis[j]) { vis[j]=1; if(my[j]==-1||path(my[j])) { my[j]=i; mx[i]=j; return 1; } } } return 0; } int hungary() { int res=0; memset(mx,-1,sizeof mx); memset(my,-1,sizeof my); for(int i=1;i<cnt;i++) { if(mx[i]==-1) { memset(vis,0,sizeof vis); res+=path(i); } } return res; } int main() { int icy,cas=1,i,j; scanf("%d",&icy); while(icy--) { scanf("%d",&n); memset(e,0,sizeof e); memset(mp,0,sizeof mp); for(i=0;i<n;i++) scanf("%s",s[i]); cnt=1; for(i=0;i<n;i++) for(j=0;j<n;j++) if(s[i][j]=='#') mp[i][j]=cnt++; for(i=0;i<n;i++) for(j=0;j<n;j++) { if(mp[i][j]) { if(i<n-1&&mp[i+1][j]) e[mp[i][j]][mp[i+1][j]]=e[mp[i+1][j]][mp[i][j]]=1; if(j<n-1&&mp[i][j+1]) e[mp[i][j+1]][mp[i][j]]=e[mp[i][j]][mp[i][j+1]]=1; } } memset(vis,0,sizeof vis); int ans=hungary(); printf("Case %d: %d\n",cas++,ans/2); } return 0; }
hdu4185 Oil Skimming
时间: 2024-10-05 05:04:48