动态规划(斜率优化)

定义

dp[i] = min{dp[j] + f(i, j)}, L(i) <= j <= R(i)

HDU3507

http://acm.hdu.edu.cn/showproblem.php?pid=3507

dp[i]表示打印前i个单词的最小代价

dp[i] = min{dp[j] + (s[i] - s[j])^2 + m}, 0 <= j < i
dp[i] = dp[j] + s[i]^2 - 2 * s[i] * s[j] + s[j]^2 + m
dp[j] + s[j]^2 = 2 * s[i] * s[j] + dp[i] - s[i]^2 - m
y = kx + b
y = dp[j] + s[j]^2
k = 2 * s[i]
x = s[j]
b = dp[i] - s[i]^2 - m

问题转换成寻找一个(x, y) = (s[j], dp[j] + s[j]^2),使得dp[i]最小,由于i是确定的,因此k是确定的,dp[i]最小等价于b最小
将斜率为k的直线向上移动,遇到第一个(x, y)时的b最小,即dp[i]最小

在这里插入图片描述

int GetY(int j1, int j2)
{
    return dp[j2] + s[j2] * s[j2] - (dp[j1] + s[j1] * s[j1]);
}

int GetX(int j1, int j2)
{
    return s[j2] - s[j1];
}

int main()
{
    int q[n], head = 0, tail = 0, i, j;
    q[tail++] = 0; // 0入队
    for (i = 1; i < n; ++i) {
        while (head + 1 < tail && GetY(q[head], q[head + 1]) <= 2 * s[i] * GetX(q[head], q[head + 1])) {
            head++; // head出队
        }
        dp[i] = dp[q[head]] + (s[i] - s[q[head]]) * (s[i] - s[q[head]]) + m;
        while (head + 1 < tail && GetY(q[tail - 1], i) * GetX(q[tail - 2], q[tail - 1]) <= GetY(q[tail - 2], q[tail - 1]) * GetX(q[tail - 1], i)) {
            tail--; // tail - 1出队
        }
        q[tail++] = i; // i入队
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值