您的位置:首页 > 其它

hdu 2282

2013-04-03 17:59 134 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2282

思路:建图很重要,一个二分图最优匹配的题目。

如果我们要移动巧克力,最后一定是把盒子中多余的巧克力移到空盒子中去,那么我们不妨以多出的每个巧克力以及每个空盒子为研究对象,这样每个巧克力只能放到一个空盒子中,每个空盒子也只能放一个巧克力,于是就可以构成一个二分图去求最优匹配了,其中边权为巧克力和空盒子的最短距离。

View Code

#include<iostream>
const int MAXN=507;
const int inf=1<<30;
using namespace std;
int match[MAXN];
int map[MAXN][MAXN];
int lx[MAXN],ly[MAXN];
bool visitx[MAXN],visity[MAXN];
int nx,ny;

int Hungary(int u){
visitx[u]=true;
for(int i=0;i<ny;i++){
if(!visity[i]&&lx[u]+ly[i]==map[u][i]){
visity[i]=true;
if(match[i]==-1||Hungary(match[i])){
match[i]=u;
return true;
}
}
}
return false;
}

void KM_prefect_match(){
int tmp;
for(int i=0;i<nx;i++){
lx[i]=-inf;
}
memset(ly,0,sizeof(ly));
for(int i=0;i<nx;i++){
for(int j=0;j<ny;j++){
lx[i]=max(lx[i],map[i][j]);
}
}
for(int i=0;i<nx;i++)
{
while(1){
memset(visitx,false,sizeof(visitx));
memset(visity,false,sizeof(visity));
if(Hungary(i))
break;
else {
tmp=inf;
for(int j=0;j<nx;j++)if(visitx[j]){
for(int k=0;k<ny;k++){
if(!visity[k]&tmp>lx[j]+ly[k]-map[j][k]){
tmp=lx[j]+ly[k]-map[j][k];
}
}
}
for(int j=0;j<nx;j++){
if(visitx[j])
lx[j]-=tmp;
}
for(int j=0;j<ny;j++){
if(visity[j])
ly[j]+=tmp;
}
}
}
}
}

int main(){
int n;
while(~scanf("%d",&n)){
int num[MAXN],X[MAXN],Y[MAXN];
memset(match,-1,sizeof(match));
nx=ny=0;
for(int i=0;i<n;i++){
scanf("%d",&num[i]);
if(!num[i]){
Y[ny++]=i;
}else {
while(num[i]>1){
X[nx++]=i;
num[i]-=1;
}
}
}
for(int i=0;i<nx;i++){
for(int j=0;j<ny;j++){
map[i][j]=-inf;
}
}
for(int i=0;i<nx;i++){
for(int j=0;j<ny;j++){
map[i][j]=-min(abs(X[i]-Y[j]),n-(abs(X[i]-Y[j])));
}
}
KM_prefect_match();
int ans=0;
for(int i=0;i<ny;i++){
if(match[i]!=-1)
ans+=map[match[i]][i];
}
printf("%d\n",-ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: