hdu 2282

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2282

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

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

View Code
  1 #include<iostream>
  2 const int MAXN=507;
  3 const int inf=1<<30;
  4 using namespace std;
  5 int match[MAXN];
  6 int map[MAXN][MAXN];
  7 int lx[MAXN],ly[MAXN];
  8 bool visitx[MAXN],visity[MAXN];
  9 int nx,ny;
 10 
 11 int Hungary(int u){
 12     visitx[u]=true;
 13     for(int i=0;i<ny;i++){
 14         if(!visity[i]&&lx[u]+ly[i]==map[u][i]){
 15             visity[i]=true;
 16             if(match[i]==-1||Hungary(match[i])){
 17                 match[i]=u;
 18                 return true;
 19             }
 20         }
 21     }
 22     return false;
 23 }
 24 
 25 
 26 void KM_prefect_match(){
 27     int tmp;
 28     for(int i=0;i<nx;i++){
 29         lx[i]=-inf;
 30     }
 31     memset(ly,0,sizeof(ly));
 32     for(int i=0;i<nx;i++){
 33         for(int j=0;j<ny;j++){
 34             lx[i]=max(lx[i],map[i][j]);
 35         }
 36     }
 37     for(int i=0;i<nx;i++)
 38     {
 39         while(1){
 40             memset(visitx,false,sizeof(visitx));
 41             memset(visity,false,sizeof(visity));
 42             if(Hungary(i))
 43                 break;
 44             else {
 45                 tmp=inf;
 46                 for(int j=0;j<nx;j++)if(visitx[j]){
 47                     for(int k=0;k<ny;k++){
 48                         if(!visity[k]&tmp>lx[j]+ly[k]-map[j][k]){
 49                             tmp=lx[j]+ly[k]-map[j][k];
 50                         }
 51                     }
 52                 }
 53                 for(int j=0;j<nx;j++){
 54                     if(visitx[j])
 55                         lx[j]-=tmp;
 56                 }
 57                 for(int j=0;j<ny;j++){
 58                     if(visity[j])
 59                         ly[j]+=tmp;
 60                 }
 61             }
 62         }
 63     }
 64 }
 65 
 66 
 67 
 68 int main(){
 69     int n;
 70     while(~scanf("%d",&n)){
 71         int num[MAXN],X[MAXN],Y[MAXN];
 72         memset(match,-1,sizeof(match));
 73         nx=ny=0;
 74         for(int i=0;i<n;i++){
 75             scanf("%d",&num[i]);
 76             if(!num[i]){
 77                 Y[ny++]=i;
 78             }else {
 79                 while(num[i]>1){
 80                     X[nx++]=i;
 81                     num[i]-=1;
 82                 }
 83             }
 84         }
 85         for(int i=0;i<nx;i++){
 86             for(int j=0;j<ny;j++){
 87                 map[i][j]=-inf;
 88             }
 89         }
 90         for(int i=0;i<nx;i++){
 91             for(int j=0;j<ny;j++){
 92                 map[i][j]=-min(abs(X[i]-Y[j]),n-(abs(X[i]-Y[j])));
 93             }
 94         }
 95         KM_prefect_match();
 96         int ans=0;
 97         for(int i=0;i<ny;i++){
 98             if(match[i]!=-1)
 99                 ans+=map[match[i]][i];
100         }
101         printf("%d\n",-ans);
102     }
103     return 0;
104 }
原文地址:https://www.cnblogs.com/wally/p/2998443.html