2424: [HAOI2010]订货
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 855 Solved: 603
[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
2 4 8
1 2 4
Sample Output
34
题解
讲道理啊看到第一眼就觉得是DP……网上一搜一大片网络流把我吓傻了,最后还是DP水过了23333
显然如果仓库在第i天之后有j的货物最小费用为f[i,j],我们设在第i天出货之前仓库里有j的货物最小费用为g[i,j],则有f[i,j]=g[i,j+u[i]],相当于把答案平移了u[i]。然后一个显然的方程式可得的g[i,j]=min{f[i-1,k]+k*w+(j-k)*d[i]} (0<=k<=j),如果直接三重循环时间复杂度显然药丸,O(nm^2)。我们可以给他变个形,g[i,j]=min{f[i-1,k]+k*w-k*d[i]} +j*d[i](0<=k<=j),显然在min函数内的值只与k有关,设s[i,k]=f[i-1,k]+k*w-k*d[i],则只要维护0<=k<=j的s[i,k]的最小值,g[i,j]=min+j*d[i]就可以了。
最后记得特殊处理一下超出容量的部分(求g[i,j]时j可以超出),然后数组可以滚动用,开一维就行了。
1 /************************************************************** 2 Problem: 2424 3 User: 1090900715 4 Language: Pascal 5 Result: Accepted 6 Time:96 ms 7 Memory:344 kb 8 ****************************************************************/ 9 10 program j01; 11 var f:array[0..10000]of longint; 12 g:array[0..20000]of longint; 13 u,d:array[0..50]of longint; 14 n,m,s,i,j,x:longint; 15 function min(a,b:longint):longint; 16 begin 17 if a<b then exit(a) else exit(b); 18 end; 19 begin 20 readln(n,m,s); 21 for i:=1 to n do read(u[i]); 22 for i:=1 to n do read(d[i]); 23 fillchar(f,sizeof(f),$3f); 24 f[0]:=0; 25 for i:=1 to n do 26 begin 27 for j:=0 to s do f[j]:=f[j]+j*m-d[i]*j; 28 x:=maxlongint; 29 for j:=0 to s do 30 begin 31 x:=min(x,f[j]); 32 g[j]:=x+d[i]*j; 33 end; 34 for j:=s+1 to s+u[i] do g[j]:=x+d[i]*j; 35 for j:=0 to s do f[j]:=g[j+u[i]]; 36 end; 37 writeln(f[0]); 38 end.