4 4 6 1 1 1 4 2 2 4 1 4 2 4 4 4 3 4 4 2 3 2 2 2 3 1 0 0
4 (1,2)--(1,3) (2,1)--(3,1) (2,3)--(3,3) (2,4)--(3,4) 3 (1,1)--(2,1) (1,2)--(1,3) (2,3)--(3,3)
题意:
问能放多少个1*2的矩阵,有几个点不能放。
代码:
#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <string.h>
#include <vector>
using namespace std;
const int MAXN = 510;
int uN,vN;//u,v的数目,使用前面必须赋值
int g[MAXN][MAXN];//邻接矩阵
int linker[MAXN];
bool used[MAXN];
bool dfs(int u)
{
for(int v = 0; v < vN;v++)
if(g[u][v] && !used[v])
{
used[v] = true;
if(linker[v] == -1 || dfs(linker[v]))
{
linker[v] = u;
return true;
}
}
return false;
}
int hungary()
{
int res = 0;
memset(linker,-1,sizeof(linker));
for(int u = 0;u < uN;u++)
{
memset(used,false,sizeof(used));
if(dfs(u))res++;
}
return res;
}
int a[110][110];
int b[100];
int main()
{
int n,m,k;
int u,v;
while(scanf("%d%d",&n,&m)==2)
{
if(n == 0 && m == 0)break;
scanf("%d",&k);
memset(a,0,sizeof(a));
while(k--)
{
scanf("%d%d",&u,&v);
u--;v--;
a[u][v] = -1;
}
int index = 0;
for(int i = 0;i < n;i++)
for(int j = 0;j < m;j++)
if(a[i][j]!=-1)
{
b[index] = i*m + j;//用b数组记录可以放的点的坐标。
a[i][j] = index++;//将可以放的点从0记录。这个操作真是tm的美,这样你匹配哪个点,你就能知道这个点的坐标,
}
uN = vN = index;
memset(g,0,sizeof(g));
for(int i = 0;i < n;i++)
for(int j= 0;j < m;j++)
if(a[i][j]!=-1 && (i+j)%2==1)
{
u = a[i][j];
if(i > 0 && a[i-1][j]!=-1)
g[u][a[i-1][j]]=1;
if(i < n-1 && a[i+1][j]!=-1)
g[u][a[i+1][j]]=1;
if(j > 0 && a[i][j-1]!=-1)
g[u][a[i][j-1]]=1;
if(j < m-1 && a[i][j+1]!=-1)
g[u][a[i][j+1]]=1;
}
int ans = hungary();
printf("%d\n",ans);
for(int i = 0;i <vN;i++)
if(linker[i]!=-1)
{
int x1 = b[i]/m;
int y1 = b[i]%m;
int x2 = b[linker[i]]/m;
int y2 = b[linker[i]]%m;
printf("(%d,%d)--(%d,%d)\n",x1+1,y1+1,x2+1,y2+1);
}
printf("\n");
}
return 0;
}