HDU 1507 Uncle Tom's Inherited Land*
题目大意:给你一个矩形,然后输入矩形里面池塘的坐标(不能放东西的地方),问可以放的地方中,最多可以放多少块1*2的长方形方块,并输出那些方块的位置。
题解:我们将所有未被覆盖的分为两种,即分为黑白格(i+j结果为奇数和偶数),然后将相邻的连边,做一遍最大匹配即可。
#include <cstdio> #include <cstring> #include <algorithm> #include <vector> using namespace std; const int N=105; vector v[N]; int q,w,m,n,k,odd,even,oddx[N],evenx[N],oddy[N],eveny[N],used[N],link[N]; int map[N][N]; struct node{int x,y,x1,y1;}ans[N]; int abs(int a){return a>0?a:-a;} bool Dfs(int k){ for(int i=0;i<v[k].size();i++){ int a=v[k][i]; if(used[a]==0){ used[a]=1; if(link[a]==-1||Dfs(link[a])){link[a]=k;return 1;} } }return 0; } bool cmp(node a,node b){return a.x<b.x||(a.x==b.x&&a.y<b.y);} int main(){ while(scanf("%d%d",&n,&m),n!=0&&m!=0){ for(int i=0;i<N;i++)v[i].clear(); scanf("%d",&k); odd=even=0; memset(map,0,sizeof(map)); for(int i=0;i<k;i++)scanf("%d%d",&q,&w),map[q][w]=1; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++)if(!map[i][j]){ if((i+j)%2==0)evenx[++even]=i,eveny[even]=j; else{oddx[++odd]=i;oddy[odd]=j;} } for(int i=1;i<=odd;i++) for(int j=1;j<=even;j++){ if(oddx[i]==evenx[j]&&abs(oddy[i]-eveny[j])==1)v[j].push_back(i); if(oddy[i]==eveny[j]&&abs(oddx[i]-evenx[j])==1)v[j].push_back(i); }int count=0; memset(link,-1,sizeof(link)); for(int i=1;i<=even;i++){ memset(used,0,sizeof(used)); if(Dfs(i))count++; }int cnt=0; printf("%d\n",count); for(int i=1;i<=odd;i++){ if(link[i]!=-1){ if(oddx[i]<evenx[link[i]]||(oddx[i]==evenx[link[i]]&&oddy[i]<eveny[link[i]])){ ans[cnt].x=oddx[i];ans[cnt].y=oddy[i]; ans[cnt].x1=evenx[link[i]];ans[cnt++].y1=eveny[link[i]]; }else{ ans[cnt].x1=oddx[i];ans[cnt].y1=oddy[i]; ans[cnt].x=evenx[link[i]];ans[cnt++].y=eveny[link[i]]; } } } sort(ans,ans+cnt,cmp); for(int i=0;i<cnt;i++)printf("(%d,%d)--(%d,%d)\n",ans[i].x,ans[i].y,ans[i].x1,ans[i].y1); } return 0; }
愿你出走半生,归来仍是少年