bzoj2424 [HAOI2010]订货 dp+单调性

[HAOI2010]订货

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 1311  Solved: 884
[Submit][Status][Discuss]

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

HINT

 

先写了个DP方程:f[i][j]=min(f[i][j],f[i-1][k]+d[i]*(j+u[i]-k)+m*k);(0<=j<=s,0<=k<=j+u[i])

  O(n*s^2),T的结果很明显

  优化一下,很容易发现其实f数组是具有一定的单调性的

  那么用单调队列来优化一下下

  当f[i-1][list[head]]+d[i]*(j+u[i]-list[head])+m*list[head]>f[i-1][list[head+1]]+d[i]*(j+u[i]-list[head+1])+m*list[head+1]的时候说明list[head+1]对于当前情况更优,所以head++,不过要判断一下list[head+1]是否<=j+u[i]

  其实f[i-1][list[head]]+d[i]*(j+u[i]-list[head])+m*list[head]>f[i-1][list[head+1]]+d[i]*(j+u[i]-list[head+1])+m*list[head+1]

  可以转化为f[i-1][list[head]]-(d[i]-m)*list[head]>f[i-1][list[head+1]]-(d[i]-m)*list[head+1],将其中不变的值去掉

 1 #include<cstring>
 2 #include<cmath>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<cstdio>
 6 
 7 #define N 57
 8 #define M 10007
 9 using namespace std;
10 inline int read()
11 {
12     int x=0,f=1;char ch=getchar();
13     while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
14     while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
15     return x*f;
16 }
17 
18 int n,m,s;
19 int u[51],d[51];
20 int f[51][11000];
21 int list[11000];
22 
23 int main()
24 {
25     n=read(),m=read(),s=read();
26     for(int i=1;i<=n;i++) u[i]=read();
27     for(int i=1;i<=n;i++) d[i]=read();
28     memset(f,63,sizeof(f));
29     f[0][0]=0;
30     for(int i=1;i<=n;i++)
31     {
32         int head=1,tail=s+1;
33         for(int j=0;j<=s;j++) list[j+1]=j;
34         for(int j=0;j<=s;j++)
35         {
36             while(head<=tail&&f[i-1][list[head]]-(d[i]-m)*list[head]>f[i-1][list[head+1]]-(d[i]-m)*list[head+1]&&list[head+1]<=j+u[i]) head++;
37             int k=list[head];
38             f[i][j]=f[i-1][k]+d[i]*(j+u[i]-k)+m*k;
39         }
40     }
41     printf("%d\n",f[n][0]);
42 }

 

posted @ 2018-04-08 16:17  Kaiser-  阅读(178)  评论(0编辑  收藏  举报