1954【线性规划与网络流24题 19】负载平衡问题

                   P1954【线性规划与网络流24题 19】负载平衡问题

时间限制 : 10000 MS 空间限制 : 65536 KB
问题描述

G公司有n个沿铁路运输线环形排列的仓库,每个仓库存储的货物数量不等。如何用最少搬运量可以使n个仓库的库存数量相同。
搬运货物时,只能在相邻的仓库之间搬运。
对于给定的n个环形排列的仓库的库存量,编程计算使n个仓库的库存数量相同的最少搬运量。

输入格式

第1行中有1个正整数n(n<=100),表示有n个仓库。第2行中有n个正整数,表示n个仓库的库存量。

输出格式

一个整数,表示最少搬运量

样例输入

5
17 9 14 16 4

样例输出

11

题解
每个人之间连一条容量无限,距离为1的边;
注意他是一个环1与n要连一条边

#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define inf 99999999
#define maxn 805
int n,sum,s,p;
int cnt=1;
int a[105];
int path[maxn],p2[maxn];
int Next[maxn],Last[maxn],End[maxn],con[maxn],Len[maxn];
bool mark[maxn];
int dis[maxn];
int start=0,mincost;
bool spfa()
{
 int i,x,y;
 queue<int>q;
 for(i=start;i<=n+1;i++) dis[i]=inf;
 memset(mark,false,sizeof(mark));
 q.push(start);
 mark[start]=true;
 dis[start]=0;
 while(q.size())
 {
  int x=q.front();
  q.pop();
  mark[x]=false;
  for(i=Last[x];i;i=Next[i])
  {
   int en=End[i];
   if(con[i]>0&&dis[en]>dis[x]+Len[i])
   {
    dis[en]=dis[x]+Len[i];
    path[en]=x;
    p2[en]=i;
    if(mark[en]==0){
     q.push(en);
     mark[en]=true;
    }
   }
  }
 }
 if(dis[n+1]<inf) return true;
 else return false;
}
void insert(int x,int y,int z,int w)
{
 cnt++;
 Next[cnt]=Last[x];
 Last[x]=cnt;
 End[cnt]=y;
 Len[cnt]=w;
 con[cnt]=z;
}
void addflow()
{
 int flow=inf,cost=0,p=0;
 for(int i=n+1;i;i=path[i])
 {
  p=p2[i];
  flow=min(flow,con[p]);
 }
 mincost+=flow*dis[n+1];
    for(int i=n+1;i;i=path[i])
    {
     p=p2[i];
     con[p]-=flow;
     con[p^1]+=flow;
 }
}
int main()
{
 int i,j,k;
 scanf("%d",&n);
 for(i=1;i<=n;i++){ scanf("%d",&a[i]);sum+=a[i];}
     p=sum/n;
    for(i=1;i<=n;i++){
     insert(0,i,a[i],0);
     insert(i,0,0,0);
 }
 for(i=1;i<=n-1;i++)
 {
  insert(i,i+1,inf,1);
  insert(i+1,i,0,-1);
  insert(i+1,i,inf,1);
  insert(i,i+1,0,-1);
 }
  insert(1,n,inf,1);
  insert(n,1,0,-1);
  insert(n,1,inf,1);
  insert(1,n,0,-1);
 for(i=1;i<=n;i++)

 {
    insert(i,n+1,p,0);
    insert(n+1,i,0,0);
 }
 while(spfa()) addflow();
 cout<<mincost;

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值