BZOJ2059: [Usaco2010 Nov]Buying Feed 购买饲料
数轴上n<=500个站可以买东西,每个站位置Xi,库存Fi,价格Ci,运东西价格是当前运载重量的平方乘距离,求买K<=10000个东西到达点E的最小代价。
f[i,j]--到第i站不买第i站东西的最大值,转移时决策的是买上一个站的东西,f[i,j]=f(i-1,k)+(j-k)*C(i-1)+j*j*(Xi-Xi-1)。
这个拆一下就可以单调队列了。
1 #include<stdio.h> 2 #include<string.h> 3 #include<stdlib.h> 4 #include<algorithm> 5 #include<queue> 6 //#include<iostream> 7 using namespace std; 8 9 int T,E,n; 10 #define maxn 511 11 struct Point{int x,f,c;}a[maxn]; 12 bool cmp(const Point &a,const Point &b) {return a.x<b.x;} 13 #define LL long long 14 #define maxm 10011 15 LL f[maxm];const LL inf=1e15; 16 LL que[maxm],head,tail,id[maxm]; 17 int main() 18 { 19 scanf("%d%d%d",&T,&E,&n); 20 for (int i=1;i<=n;i++) 21 scanf("%d%d%d",&a[i].x,&a[i].f,&a[i].c); 22 sort(a+1,a+1+n,cmp);a[++n].x=E; 23 for (int i=1;i<=T;i++) f[i]=inf;f[0]=0; 24 for (int i=2;i<=n;i++) 25 { 26 head=tail=0; 27 for (int j=0;j<=T;j++) 28 { 29 LL tmp=f[j]-1ll*a[i-1].c*j; 30 while (head<tail && que[tail-1]>=tmp) tail--; 31 while (head<tail && id[head]<j-a[i-1].f) head++; 32 que[tail]=tmp;id[tail++]=j; 33 f[j]=que[head]+1ll*a[i-1].c*j+1ll*j*j*(a[i].x-a[i-1].x); 34 } 35 } 36 printf("%lld\n",f[T]); 37 return 0; 38 }