bzoj2424: [HAOI2010]订货


Description

某公司估计市场在第i个月对某产品的需求量为Ui,已知在第i月该产品的订货单价为di,上个月月底未销完的单位产品要付存贮费用m,假定第一月月初的库存量为零,第n月月底的库存量也为零,问如何安排这n个月订购计划,才能使成本最低?每月月初订购,订购后产品立即到货,进库并供应市场,于当月被售掉则不必付存贮费。假设仓库容量为S。

Input

第1行:n, m, S (0<=n<=50, 0<=m<=10, 0<=S<=10000)
第2行:U1 , U2 , ... , Ui , ... , Un (0<=Ui<=10000)
第3行:d1 , d2 , ..., di , ... , dn (0<=di<=100)

Output

只有1行,一个整数,代表最低成本

Sample Input

3 1 1000
2 4 8
1 2 4

Sample Output

34
思路:良心网络流拉,拆点拆拉大半天才发现是个傻逼题。。。
考虑下建图:
从S-》i建一条流量为无穷大,费用为di的边(很容易理解,你可以无限制的订货嘛)
从i->i+1建一条流量为X,费用为m的边,(仓库的容量所X不能超过X)
最后是i->t建一条费用为Ui的边
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#define inf 0x7ffffff
using namespace std;
inline int read()
{
char ch;int s=0,f=1;ch=getchar();
while(ch>'9'||ch<'0') { if(ch=='-') f*=-1;ch=getchar(); }
while(ch>='0'&&ch<='9') { s=s*10+ch-48;ch=getchar(); }
return s*f;
}
const int maxn = 1005,maxm = 50005;
struct node {
 int u,v,nxt,cap,cost;
}e[maxm];
int cnt = 1,n,m,X,s,t,head[maxn];
int dis[maxn],deep[maxn];
void add(int u,int v,int cap,int cost)
{
 cnt ++;e[cnt].u=u,e[cnt].v=v,e[cnt].cap=cap,e[cnt].cost=cost;
 e[cnt].nxt=head[u],head[u]=cnt;
}
int fa[maxn];
bool vis[maxn];
bool spfa()
{
queue<int> q;
for(int i=1;i<=t;i++) dis[i]=inf,vis[i]=false;
dis[s]=0,q.push(s);vis[s]=true;
while(!q.empty())
 {
  int x=q.front(); q.pop();
  for(int i=head[x];i;i=e[i].nxt)
   {
    int to=e[i].v;
     if(e[i].cap)
     if(dis[to]>dis[x]+e[i].cost)
    { dis[to]=dis[x]+e[i].cost; fa[to]=i; if(!vis[to]) { vis[to]=true; q.push(to); }  }
 }
 vis[x]=false;
 }
 return dis[t]<inf;
}
int ans = 0;
void mcf()
{
 int i=t,flow=inf;
 while(i!=s)
 {
  int now = fa[i];
  flow=min(e[now].cap,flow);
  i=e[now].u;
 }
 i=t;
 while(i!=s)
 {
  int now = fa[i];
  e[now].cap-=flow,e[now^1].cap+=flow;
  i=e[now].u;
 }
 ans+=flow*dis[t];
}
int main()
{
//freopen("1.in","r",stdin);
n=read(),m=read(),X=read();
s=n+1,t=s+1;
int x;
for(int i=1;i<=n;i++) x=read(),add(i,t,x,0),add(t,i,0,0);
for(int i=1;i<=n;i++) x=read(),add(s,i,inf,x),add(i,s,0,-x);
for(int i=1;i<n;i++) add(i,i+1,X,m),add(i+1,i,0,-m);
while(spfa()) mcf();
printf("%d",ans);
 return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值