Chocolate
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 274 Accepted Submission(s): 139
Problem Description
Lethe loves eating chocolates very much. In Lethe's birthday, her good friend echo brings N boxes to her, and makes the boxes on the circle. Furthermore, echo tells Lethe that there are many chocolates in the boxes, but the total number of chocolates doesn't exceed N. Also, echo wants Lethe to displace the chocolates in such a way that in each box remains no more than one chocolate. In one move she can shift one chocolate from current box to its neighboring box. (Each box has two neighboring boxes). Can you tell Lethe the minimum number of move to achieve this goal?
Input
There are multi-cases (The total number of cases won't exceed 20). First line is an integer N(1<=N<=500), the total number of boxes. Then N lines follow, each line includes a number, indicates the number of chocolates in the box.
Output
Output the minimum number of move.
Sample Input
10 1 3 3 0 0 2 0 0 0 0
Sample Output
9
Source
Recommend
lcy
拆点建图+KM算法。
说有一圈巧克力,要移动让每个盒子最多一个,问最小移动方法。
把每个多余的巧克力(拆点)和空盒子建二分图,权值就是移动的步数,由于求的是最小移动步数,因此把权值取负的做KM即可。
代码
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <algorithm>
using namespace std;
int n;
int a[500];
int Map[500][500];
int more[500];
int less[500];
int Count(int x,int y)
{
return min(abs(y-x),n-abs(y-x));
}
const int inf = 10000;
int m,lx[555],ly[555],match[555];
bool x[555],y[555];
bool SearchPath(int u)
{
int v;
x[u] = true;
for (v = 1; v <= n; v++)
if(!y[v] && ly[v] + lx[u] == Map[u][v])
{
y[v] = true;
if (match[v] == -1 || SearchPath(match[v]))
{
match[v] = u;
return true;
}
}
return false;
}
int KM()
{
int i,j,k,d;
for (i = 1; i <= n; i++)
while(1)
{
memset(x,false,sizeof(x));
memset(y,false,sizeof(y));
if (SearchPath(i))
break;
d = inf;
for (j = 1; j <= n; j++)
if (x[j])
{
for (k = 1; k <= n; k++)
if (!y[k])
if (d > lx[j] + ly[k] - Map[j][k])
d = lx[j] + ly[k] - Map[j][k];
}
for (j = 1; j <= n;j ++)
{
if (x[j]) lx[j] -= d;
if (y[j]) ly[j] += d;
}
}
int ans = 0;
for (i = 1; i <= n; i++)
ans += Map[match[i]][i];
return ans;
}
int Solve()
{
int i,j;
memset(ly,0,sizeof(ly));
for (i = 1; i <= n; i++)
{
lx[i] = -inf;
for (j = 1; j <= n; j++)
{
if (lx[i] < Map[i][j])
{
lx[i] = Map[i][j];
}
}
}
memset(match,-1,sizeof(match));
return KM();
}
int main()
{
int i,j,up1,up2,up,k;
while(scanf("%d",&n)!=EOF)
{
up1=up2=1;
for (i=0;i<n;i++)
{
scanf("%d",&a[i]);
if (a[i]>1) more[up1++]=i;
if (a[i]==0) less[up2++]=i;
}
memset(Map,0,sizeof(Map));
up=1;
for (i=1;i<up1;i++)
{
for (j=2;j<=a[more[i]];j++)
{
for (k=1;k<up2;k++)
{
Map[up][k]=-Count(more[i],less[k]);
}
up++;
}
}
n=max(up,up2)-1;
printf("%d\n",-Solve());
}
return 0;
}