(1)题意:
选取两个连续的空地作为一个单元,其中给出一些标记的池塘,池塘不能被选择,求出最多可以选择多少个单元的地方。
每个地方用两个坐标来表示。
(2)思路:
将图中所有能够选取的空地按照(i+j)%2==1,和(i+j)%2==0,分为两部分,
如果这两部分相邻,这两个个点之间有一条边。
然后用二分图求出这张图的最大匹配就是最多的连续的面积。
(3)代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn = 1e4+10;
int head[maxn],vis[maxn],pre[maxn],tot,n,m,k,mp[120][120],len,bj[maxn];
struct Node{
int v,nxt;
}cur[maxn<<2];
int dx[4] = {0,0,-1,1};
int dy[4] = {1,-1,0,0};
vector <int> v1,v2;
void Init(){
memset(head,-1,sizeof(head));
tot = 0;
}
void Add(int x,int y){
cur[tot].v = y;
cur[tot].nxt = head[x];
head[x] = tot++;
}
int dfs(int x){
for(int i=head[x];i!=-1;i=cur[i].nxt){
int y = cur[i].v;
if(vis[y]==0){
vis[y] = 1;
if(pre[y]==-1||dfs(pre[y])){
pre[y] = x;
return true;
}
}
}
return false;
}
int fun(){
memset(bj,0,sizeof(bj));
memset(pre,-1,sizeof(pre));
len = v1.size();
int ans = 0;
for(int i=0;i<len;i++){
memset(vis,0,sizeof(vis));
if(dfs(v1[i])){
bj[v1[i]] = 1;ans++;
}
}
return ans;
}
int main(void){
while(~scanf("%d%d",&n,&m)&&(n+m)){
scanf("%d",&k);
v1.clear();
v2.clear();
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++) mp[i][j] = 0;
Init();
for(int i=0;i<k;i++){
int x,y;scanf("%d%d",&x,&y);
mp[x][y] = 1;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(mp[i][j]==0&&(i+j)%2==1){
int x = (i-1)*m+j;
v1.push_back(x);
for(int k=0;k<4;k++){
int ti = i+dx[k];
int tj = j+dy[k];
if(ti>=1&&ti<=n&&tj>=1&&tj<=m&&mp[ti][tj]==0){
int y = (ti-1)*m+tj;
Add(x,y);
}
}
}
else if(mp[i][j]==0&&(i+j)%2==0) v2.push_back((i-1)*m+j);
int ans = fun();
printf("%d\n",ans);
int ll = v2.size();
for(int i=0;i<ll;i++)
if(bj[pre[v2[i]]]==1){
int x1 = pre[v2[i]]/m+1,y1 = pre[v2[i]]%m;
if(y1==0){
y1 = m;x1--;
}
int x2 = v2[i]/m+1,y2 = v2[i]%m;
if(y2==0){
y2 = m;x2--;
}
printf("(%d,%d)--(%d,%d)\n",x1,y1,x2,y2);
}
printf("\n");
}
return 0;
}