1. 程式人生 > >Uncle Tom's Inherited Land*

Uncle Tom's Inherited Land*

bits sizeof 離散化 否則 esp i++ 並且 一個 clas

最大匹配問題

題意:題目意思:
給定一個 n * m 的矩陣格子, 第二行給定一個k值表示池塘,接下來給出池塘坐標,要求的就是在不是池塘的區域用1 * 2 的小矩形填充它 ,問 最多能填充幾個小矩形,並且打印出所有矩陣!

這題拿到手毫無頭緒 是這個專題最難的一題了

這題值得多打幾遍

#include<bits/stdc++.h>
using namespace std;
#define N 105

int mp[N][N];
int used[N];
int vis[N];
int n,m,r,c;
int dx[4]={0,1,0,-1};
int dy[4]={1,0,-1,0};
int flag[N][N]; int ans[N][2]; int cnt; vector<int>g[N*N]; bool dfs(int x) { for(int j=0;j<g[x].size();j++) { if(!used[ g[x][j] ]) //所有的j都改為了g[x][j] { used[ g[x][j] ]=1; if(!vis[ g[x][j] ]||dfs(vis[ g[x][j] ])) { vis[ g[x][j] ]
=x; return true; } } } return false; } int find1(void) { int ans=0; memset(vis,0,sizeof(vis)); for(int i=1;i<=cnt-1;i++) { memset(used,0,sizeof(used)); if(dfs(i))ans++; } return ans; } bool inmap(int
x,int y) { if(x>=1&&x<=n&&y>=1&&y<=m)return true; else return false; } int main() { while(scanf("%d%d",&n,&m),n||m) { memset(mp,0,sizeof(mp)); memset(flag,0,sizeof(flag)); memset(ans,0,sizeof(ans)); for(int i=0;i<=N*N;i++)g[i].clear(); int q; scanf("%d",&q); while(q--) { int a,b; scanf("%d%d",&a,&b); mp[a][b]=1; } cnt=1; for(int i=1;i<=n;i++)//掃描各個點 進行離散化 for(int j=1;j<=m;j++) if(mp[i][j]==0) { ans[cnt][0]=i; ans[cnt][1]=j;//這個數組用的巧妙!! flag[i][j]=cnt++;//從小到大標記各個有效點 } for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(flag[i][j]) if( 1&(i+j) )//只處理奇數的 可以提高效率 否則的話 ans為兩倍(匹配兩次) 並且打印各個點就會出錯!!很重要 { for(int k=0;k<4;k++)//類似dfs 掃描一個點 將其匹配的點(就是相鄰點)存入匹配向量!!! { int x=i+dx[k]; int y=j+dy[k]; if(inmap(x,y)&&flag[x][y]) g[ flag[i][j] ].push_back( flag[x][y] ); } } printf("%d\n",find1()); for(int i=1;i<cnt;i++)//使用vis數組來打印 !這時用上了之前所處理的記錄數組 if(vis[i]) { printf("(%d,%d)--(%d,%d)\n", ans[i][0],ans[i][1],ans[ vis[i] ][0],ans[ vis[i] ][1] ); } printf("\n"); } }

Uncle Tom's Inherited Land*