zoukankan      html  css  js  c++  java
  • 斜率优化

    斜率优化

    斜率优化是个难点,或许做多了就好了吧。

    还是和各种DP优化一样,我们先想出比较暴力的转移方程:f[i] = max{f[j] + xxx},如果发现xxx里有i的相关项与j的相关项相乘的话,就可能是斜率优化了。

    我们通常以j的相关项为横坐标,f[j]为纵坐标,把候选决策集合(点集)表示出来,再把f[j]用j的相关项和i的相关项表示出来,如果发现f[j] = xxx是斜率已知的直线,纵截距代表f[i],那么用斜率优化就基本没错了。

    例题:301. 任务安排2

    正好遇到这道题就说一下:如果某个状态进行某种决策后,其对后的影响已知,不妨让状态顺便包含一下该影响。这种思想叫“费用提前计算”(by lyd)

    如这道例题,状态f[i]如果表示将前i件任务分批处理所需最小费用(含S对以后的影响),那么这道题将由n³降到n²。

    代码:

    struct vectors{
    	int x;
    	int y;
    	vectors(int xx = 0, int yy = 0){x = xx, y = yy;}
    	vectors operator +(const vectors a)const {
    		return vectors(x + a.x, y + a.y);
    	}
    	vectors operator -(const vectors a)const {
    		return vectors(x - a.x, y - a.y);
    	}
    	int operator *(const vectors a)const {
    		return x * a.y - y * a.x;
    	}
    }q[N << 2], xl;
    int main() {
    	...
    	for (register int i = 1; i <= n; ++i) {
    		tmp = s * csum[n] + tsum[i] * csum[i];
    		f[i] = tmp;
    		xl = vectors(1, s + tsum[i]);
    		while (front + 1 < rear && (q[front + 2] - q[front + 1]) * xl >= 0)	front++;
    		if (front < rear)	f[i] = min(f[i], tmp + q[front + 1].y - q[front + 1].x * (s + tsum[i]));
    		xl = vectors(csum[i], f[i]);
    		while (front < rear - 1 && (q[rear] - q[rear - 1]) * (xl - q[rear - 1]) <= 0)	rear--;
    		q[++rear] = xl;
    	}
        
    	printf("%lld
    ", f[n]);
    }
    

    注意!!

    写正常斜率优化的第二个While(取答案)时,一定记得... * (xl - q[rear - 1])而不是... * xl!!(计算几何没学好)

    果然计算几何没学好

    斜率优化的第二个While(取答案)时,是(stk[] - stk[]) * xl而不是(stk[] - stk[]) * (stk[] + xl)!!!

    注意斜率是 xl(1, ...),而不是 xl(...)

    注意计算几何要用 <= 而不要用 <。

  • 相关阅读:
    POJ 3468 A Simple Problem with Integers
    BZOJ 4430 Guessing Camels
    POJ 2309 BST
    POJ 1990 MooFest
    cf 822B Crossword solving
    cf B. Black Square
    cf 828 A. Restaurant Tables
    Codefroces 822C Hacker, pack your bags!
    [HDU 2255] 奔小康赚大钱
    [BZOJ 1735] Muddy Fields
  • 原文地址:https://www.cnblogs.com/JiaZP/p/13320906.html
Copyright © 2011-2022 走看看