Description
Input
Output
Sample Input
100 1
15 15
20 5
1 100
输入解释:
共有4块土地.
Sample Output
500
HINT
FJ分3组买这些土地: 第一组:100x1, 第二组1x100, 第三组20x5 和 15x15 plot. 每组
的价格分别为100,100,300, 总共500.
这题很早做的,想再推下斜率优化的题。结果果然爆掉了。。。
以前一开始连DP的思路都没有。。更别提优化了。。
//================================================================================================
对于读入的随机数据想看出DP的方法是很难的。但是考虑要用到的是某些块里面最大的和最小的值,考虑排序。
先用一个关键字排序。长和宽没有本质区别。
可以发现,对于两个矩形,如果第一个矩形的长和宽都不大于第二个,那么买第二个的时候就可以顺带买掉第一块,因为这个时候第一块是没有任何代价的(我这里称之为第一块被第二块包含)。
那么去掉了所有“被包含”的矩形后,经过排序的长宽序列会有个很有用的性质:长度序列不降的同时宽度序列不增(反之亦同)。
那么动归的阶段性就很明显了:购买前i块的消费。
转移方程为:f[i]=min(f[j]+a[j+1]*b[i])
这里定义a数组经过排序后是单调不升的,b数组相反。这个和下面程序的表达不同。。。注意注意!!
为了操作方便,可以在事先把a数组整体前移一位。则方程可以表示为:
f[i]=min(f[j]+a[j]*b[i])
列出了转移方程是不是就解决了?如果每次遍历0~i-1必然超时、、
考虑两个决策f[j],f[k]并假设j<k。
如果对于f[i],从f[j]转移来比从f[k]转移来更优,那么有:
f[j]+a[j]*b[i]<f[k]+a[k]*b[i]
移项得:
b[i]<(f[k]-f[j])/(a[j]-a[k])
为方便表示,定义d(j,k)=(f[k]-f[j])/(a[k]-a[j])
这个式子有什么用呢?
考虑:b[i]为不降的序列。所以当存在i,j,k三个决策时,并且满足i<j<k。如果d(i,k)>d(j,k)那么j决策就是无用的决策。因为如果i决策都不如k优了,那么就是说d(i,k)<b[now],那么d(j,k)肯定也小于b[now]。也就是说决策i比决策j的生命力更强、
那么,就可以开一个单调队列,存可能转移的决策,并使得d值递增。
额。。。就讲这么多了。。。剩下的自己YY吧。。
程序里面维护队列就两句话,而且为了省变量,判断句又臭又长。。。
注意:
1.在更新当前决策的时候,往后推队列的头指针,使得队列头两个的d值满足b[i]的约束。
2.在更新完当前决策后都要入队,入队的时候为了保持d值的单调性要往前推尾指针。
3.推尾指针的时候队尾两个分别与当前决策点求出d值,比较大小(一开始变成求d(尾两个)和d(尾,当前)了。。于是就WA掉了)。
4.搞清楚大小关系!!!!!
AC CODE
program bzoj_1597;
var a,b,f:array[0..50000] of int64;
//============================================================================
procedure qsort(l,r:longint);
var i,j:longint;
begin
end;
//============================================================================
begin
end.