题目地址:
http://acm.hdu.edu.cn/showproblem.php?pid=1507
题目概述:
给一个n*m的农场,其中有一些点是水池,现在需要你用2*1的格子去填充整个农场,保证所有的2*1的格子中没有水池并且相互之间没有重合部分,求出能放入的最大格子数并任意输出一种放置方案。
大致思路:
首先一个n*m的矩阵一定能保证变成一张二分图,用二分图染色来建立这张二分图即可,对于水池颜色设置为-1,然后在二分图上的最大匹配即为答案,输出方案时根据匈牙利算法的left来输出就好。
注意在转化成二分图时记得离散化,因为n*m有可能达到10000,而农场中不是水池的点最多只有50个。
代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cmath> 5 #include <vector> 6 #include <ctime> 7 #include <map> 8 #include <queue> 9 #include <cstring> 10 #include <algorithm> 11 using namespace std; 12 13 #define sacnf scanf 14 #define scnaf scanf 15 #define maxn 110 16 #define maxm 26 17 #define inf 1061109567 18 #define Eps 0.00001 19 const double PI=acos(-1.0); 20 #define mod 7 21 #define MAXNUM 10000 22 void Swap(int &a,int &b) {int t=a;a=b;b=t;} 23 double Abs(double x) {return (x<0)?-x:x;} 24 typedef long long ll; 25 typedef unsigned int uint; 26 27 int n,m,cnt=1; 28 queue<int> q; 29 int G[maxn][maxn],edge[maxn][2]; 30 int color[maxn][maxn][2]; 31 int vis[maxn],l[maxn]; 32 33 int dx[]={1,0,-1,0}; 34 int dy[]={0,1,0,-1}; 35 36 bool dfs(int u) 37 { 38 for(int i=1;i<cnt;i++) 39 { 40 if(!G[u][i]) continue; 41 if(!vis[i]) 42 { 43 vis[i]=1; 44 if(l[i]==-1||dfs(l[i])) 45 { 46 l[i]=u; 47 return true; 48 } 49 } 50 } 51 return false; 52 } 53 54 int hungary() 55 { 56 memset(l,-1,sizeof(l)); 57 int ans=0; 58 while(!q.empty()) 59 { 60 int i=q.front();q.pop(); 61 //printf(" %d ",i); 62 memset(vis,0,sizeof(vis)); 63 if(dfs(i)) ans++; 64 } 65 return ans; 66 } 67 68 void paint(int x,int y,int c) 69 { 70 color[x][y][1]=cnt; 71 edge[cnt][0]=x;edge[cnt][1]=y; 72 color[x][y][0]=c;cnt++; 73 if(c==1) q.push(color[x][y][1]); 74 int t1=color[x][y][1]; 75 for(int i=0;i<4;i++) 76 { 77 int nx=x+dx[i]; 78 int ny=y+dy[i]; 79 if(nx>0&&nx<=n&&ny>0&&ny<=m&&color[nx][ny][0]!=-1) 80 { 81 if(color[nx][ny][0]==2) 82 { 83 paint(nx,ny,c^1); 84 int t2=color[nx][ny][1]; 85 G[t1][t2]=G[t2][t1]=1; 86 } 87 else if((color[nx][ny][0])^c) 88 { 89 int t2=color[nx][ny][1]; 90 G[t1][t2]=G[t2][t1]=1; 91 } 92 } 93 } 94 } 95 96 void build_G() 97 { 98 for(int i=1;i<=n;i++) 99 { 100 for(int j=1;j<=m;j++) 101 { 102 if(color[i][j][0]==2) paint(i,j,1); 103 } 104 } 105 } 106 107 int main() 108 { 109 //freopen("data.in","r",stdin); 110 //freopen("data.out","w",stdout); 111 //clock_t st=clock(); 112 while(~scanf("%d%d",&n,&m)) 113 { 114 if(n==0&&m==0) break; 115 int k,x,y;scanf("%d",&k); 116 for(int i=1;i<=n;i++) 117 for(int j=1;j<=m;j++) 118 color[i][j][0]=2; 119 for(int i=1;i<=n*m-k;i++) 120 for(int j=1;j<=n*m-k;j++) 121 G[i][j]=0; 122 cnt=1; 123 for(int i=1;i<=k;i++) 124 { 125 scanf("%d%d",&x,&y); 126 color[x][y][0]=-1; 127 } 128 build_G(); 129 int ans=hungary(); 130 printf("%d ",ans); 131 for(int i=1;i<cnt;i++) 132 { 133 if(l[i]==-1) continue; 134 printf("(%d,%d)--(%d,%d) ",edge[i][0],edge[i][1],edge[l[i]][0],edge[l[i]][1]); 135 } 136 printf(" "); 137 } 138 //clock_t ed=clock(); 139 //printf(" Time Used : %.5lf Ms. ",(double)(ed-st)/CLOCKS_PER_SEC); 140 return 0; 141 }