Hdu-3507 Print Article

来源:互联网 发布:桃子圈微博全数据 编辑:程序博客网 时间:2024/06/08 00:21

题目链接


定义状态dp[i]表示打印前i个单词的最小成本。
dp[i] = min(dp[j] + (sum[i] – sum[j]) ^ 2)
dp[i] = min(dp[j] + sum[j]^2 – 2*sum[i]*sum[j]) + sum[i]^2
dp[j] + sum[j]^2 –(dp[k] + sum[k]^2) < 2*sum[i]*(sum[j] – sum[k])
只需要用斜率优化即可。


由于此题比较基础,所以代码故意写复杂一点一边理解,在以后较难题目中将贴出简略代码

#include <cstdio>#include <cstring>#include <iostream>using namespace std;#define N 500000 + 10#define LL long long#define cls(a) memset( a, 0, sizeof(a))struct P{    LL x, y;};P q[N];int m, n;LL dp[N], c[N], sum[N];int l, r;P operator - ( P a, P b ){    P p;    p.x = a.x - b.x;    p.y = a.y - b.y;    return p;}LL operator * ( P a, P b ){    return a.x * b.y - b.x * a.y;}bool init(){    if( scanf( "%d%d", &n, &m) == EOF ) return false;    cls(c), cls(sum), cls(dp), cls(q);    for ( int i = 1; i <= n; i++) scanf( "%d", &c[i]);    sum[0] = 0;    for ( int i = 1; i <= n; i++) sum[i] = sum[i-1] + c[i];    l = 1, r = 2;    dp[0] = 0, dp[1] = m+sum[1]*sum[1];    q[1].x=sum[1], q[1].y=dp[1]+sum[1]*sum[1];    return true;}void insert( LL x, LL y ){     P p;     p.x = x, p.y = y;     for (; l<r && (p-q[r-1])*(q[r]-q[r-1]) >= 0;r--);     q[++r]=p;}void Dp(){    for ( int i = 1; i <= n; i++){        LL k = 2*sum[i];        for  (; l<r && q[l].y-q[l].x*k > q[l+1].y-q[l+1].x*k;l++);        dp[i] = q[l].y - k * q[l].x + sum[i]*sum[i] + m;        insert( sum[i], sum[i]*sum[i]+dp[i]);     }       printf( "%d\n", dp[n]);}int main(){    while ( init() ){        Dp();    }    return 0;}*/
原创粉丝点击