您的位置:首页 > 编程语言 > Go语言

poj 2195-Going Home解题报告

2012-05-03 19:20 295 查看
链接:http://poj.org/problem?id=2195

这道题是二分图的最佳匹配问题,而且属于最小匹配,km算法的模版题,题目保证了人数和房子数相等,这是自己第一道km算法题,刚开始对km算法不理解,看各种讲解,终于搞懂了其运行过程和能求出解的原因。km算法保证在整个算法的运行过程中对于匹配x,y保证lx[x]+ly[y]>=w(x,y);最终找到的是lx[x]+ly[y]=w(x,y)的解。

View Code

#include<iostream>
#include<cstdio>
#include<cstring>
#define N 200
#define inf 0x7fffffff
using namespace std;
struct point
{
int x,y;
};
point ph
,pm
;
int lx
,ly
;
int map

;
int match
;
int usedx
,usedy
,flag;
char g

;
int abs(int a)
{
return a>=0?a:-a;
}
int max(int a,int b)
{
return a>b?a:b;
}
int min(int a,int b)
{
return a<b?a:b;
}
int h,m;
void build()
{
int i,j;
for(i=1;i<=h;i++)
for(j=1;j<=m;j++)
map[i][j]=abs(ph[i].x-pm[j].x)+abs(ph[i].y-pm[j].y);
}
bool dfs(int x)
{
int i,j,k;
usedx[x]=flag;
for(i=1;i<=m;i++)
{
if(usedy[i]!=flag&&lx[x]+ly[i]==map[x][i])
{
usedy[i]=flag;
if(match[i]==-1||dfs(match[i]))
{
match[i]=x;
return true;
}
}
}
return false;
}
int km()
{
memset(lx,127,sizeof(lx));
memset(ly,0,sizeof(ly));
build();
flag=0;
int res=0;
int i,j,k,d;
for(i=1;i<=h;i++)
for(j=1;j<=m;j++)
lx[i]=min(lx[i],map[i][j]);//最大权匹配就取最大值,最小权匹配就取最小值
memset(match,-1,sizeof(match));
for(i=1;i<=h;i++)
{
flag++;
while(!dfs(i))
{
d=inf;
for(j=1;j<=h;j++)
{
if(usedx[j]==flag)
for(k=1;k<=m;k++)
if(usedy[k]!=flag)
d=min(map[j][k]-lx[j]-ly[k],d);
}
for(j=1;j<=h;j++)
if(usedx[j]==flag)
lx[j]+=d;
for(j=1;j<=m;j++)
{
if(usedy[j]==flag)
ly[j]-=d;
}
flag++;
}
}
for(i=1;i<=m;i++)
res+=map[match[i]][i];
return res;
}
int main()
{
int r,c,i,j,k;
char s;
while(scanf("%d%d",&r,&c)&&(r||c))
{
h=m=0;
for(i=1;i<=r;i++)
scanf("%s",g[i]+1);
for(i=1;i<=r;i++)//建图过程
for(j=1;j<=c;j++)
{
if(g[i][j]=='H')
{
ph[++h].x=i;
ph[h].y=j;
}
if(g[i][j]=='m')
{
pm[++m].x=i;
pm[m].y=j;
}
}
//printf("%d %d\n",h,m);
printf("%d\n",km());
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: