Print Article /// 斜率优化DP oj26302

题目大意:

典题

数学分析 G(a,b)<sum[i]时 a优于b

G(a,b)<G(b,c)<sum[i]时 b必不为最优

#include <bits/stdc++.h>
#define N 500005
using namespace std;
int n,m,dp[N],deq[N],sum[N]; // deq[]为单调队列 sum[]为数组的前缀和
int DP(int i,int j) {
    return dp[j]+m+(sum[i]-sum[j])*(sum[i]-sum[j]);
}
int UP(int j,int k) { //yj-yk的部分
    return dp[j]+sum[j]*sum[j]-(dp[k]+sum[k]*sum[k]);
}
int DOWN(int j,int k) {//xj-xk的部分
    return 2*(sum[j]-sum[k]);
}
/*
由分析 当0<a<b<i时
若(ya-yb)/(xa-xb)<sum[i]
此处表达为G(a,b)<sum[i] 则j优于k

若存在a,b和b,c满足上述要求
即存在G(a,b)<sum[i] G(b,c)<sum[i]
若G(a,b)<G(b,c) 则b肯定不为最优点
*/
int main()
{
    while(~scanf("%d%d",&n,&m)) {
        sum[0]=dp[0]=0;
        for(int i=1;i<=n;i++) {
            int num; scanf("%d",&num);
            sum[i]=sum[i-1]+num;
        }
        int head=0, tail=0;
        deq[tail++]=0;
        for(int i=1;i<=n;i++) {
            while(head+1<tail && UP(deq[head+1],deq[head])<=sum[i]
                                *DOWN(deq[head+1],deq[head]))
                head++; /// G(head+1,head)<=sum[i] 即head+1优于head 则去掉head
            dp[i]=DP(i,deq[head]); // 用此时的最优head更新dp[i]
            while(head+1<tail && UP(i,deq[tail-1])*DOWN(deq[tail-1],deq[tail-2])
                               <=DOWN(i,deq[tail-1])*UP(deq[tail-1],deq[tail-2]))
                tail--;
            /// 如果此时G(i,tail-1)<=G(tail-1,tail-2)<=sum[i] 则说明tail-1对应点为可删去
            deq[tail++]=i;
        }
        printf("%d\n",dp[n]);
    }
    return 0;
}/*纠结了一下维护单调队列时为什么判断条件是<=第一处 G(head+1,head)=sum[i] 说明 两者平等 不存在谁更优这个问题而仍然 head++; 是因为既然两者平等 那么只要留一个就可以了第二处 G(i,tail-1)=G(tail-1,tail-2) 说明 两者斜率相等 即 i,tail-1,tail-2 三个对应点在同一条直线上那么 tail-1 这个点可以直接忽略 所以继续 tail--;*/

原文地址:https://www.cnblogs.com/zquzjx/p/9162040.html

时间: 2024-11-04 22:28:16

Print Article /// 斜率优化DP oj26302的相关文章

hdu3507 Print Article[斜率优化dp入门题]

Print Article Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)Total Submission(s): 11761    Accepted Submission(s): 3586 Problem Description Zero has an old printer that doesn't work well sometimes. As it is antiqu

[hdu3507 Print Article]斜率优化dp入门

题意:需要打印n个正整数,1个数要么单独打印要么和前面一个数一起打印,1次打印1组数的代价为这组数的和的平方加上常数M.求最小代价. 思路:如果令dp[i]为打印前i个数的最小代价,那么有 dp[i]=min(dp[j]+(sum[i]-sum[j])2+M),j<i 直接枚举转移是O(n2)的,然而这个方程可以利用斜率优化将复杂度降到O(n). 根据斜率优化的一般思路,对当前考虑的状态i,考虑决策j和k(j<k),如果k比j优,那么根据转移方程有:dp[k]+(sum[i]-sum[k])2

HDU3507 Print Article (斜率优化DP基础复习)

传送门 大意:打印一篇文章,连续打印一堆字的花费是这一堆的和的平方加上一个常数M. 首先我们写出状态转移方程 :f[i]=f[j]+(sum[i]?sum[j])2+M; 设 j 优于 k. 那么有 f[j]+(sum[i]?sum[j])2<f[k]+(sum[i]?sum[k])2 移项得出 (f[j]+sum[j]2)?(f[k]+sum[j]2)2?(sum[j]+sum[k])<sum[i] 这就是一个很理想的斜率式了. #include<cstdio> #include

hdu 3507 Print Article —— 斜率优化DP

题目:http://acm.hdu.edu.cn/showproblem.php?pid=3507 设 f[i],则 f[i] = f[j] + (s[i]-s[j])*(s[i]-s[j]) + m 即 f[j] + s[j]*s[j] = 2*s[i]*s[j] + f[i] - s[i]*s[i] - m 于是维护下凸包即可: 写成 double 的 slp 总是不对,把分母乘到对面就对了... 代码如下: #include<iostream> #include<cstdio>

HDU 3507 Print Article 斜率优化

Print Article Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)Total Submission(s): 4810    Accepted Submission(s): 1451 Problem Description Zero has an old printer that doesn't work well sometimes. As it is antique

hdu3507Print Article(斜率优化dp)

Print Article Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)Total Submission(s): 12824    Accepted Submission(s): 3967 Problem Description Zero has an old printer that doesn't work well sometimes. As it is antiqu

Print Article hdu 3507 一道斜率优化DP 表示是基础题,但对我来说很难

Print Article Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)Total Submission(s): 4990    Accepted Submission(s): 1509 Problem Description Zero has an old printer that doesn't work well sometimes. As it is antique

HDU 3507 Print Article(斜率优化DP)

题目链接 题意 : 一篇文章有n个单词,如果每行打印k个单词,那这行的花费是,问你怎么安排能够得到最小花费,输出最小花费. 思路 : 一开始想的简单了以为是背包,后来才知道是斜率优化DP,然后看了网上的资料,看得还挺懂的,不过我觉得如果以后真遇到斜率DP,要推起来肯定不简单..... 网上资料1 网上资料2 1 #include <iostream> 2 #include <stdio.h> 3 4 using namespace std; 5 6 int q[500005],dp

HDU3507 Print Article(经典斜率优化dp)

一道很老的斜率优化dp 斜率优化看上去很难,其实是有技巧的 . 对于dp题目,如果你想优化他,一定要先列出朴素的表达式并观察性质 对于本题我们可以发现,如果要更新dp[i],我们就要从前面找到dp[j]+(s[i]-s[j])^2+m的最小值,其中s是前缀和 我们就可以猜测,一定有很多不可能转移的内容,我们应该如何删除它从而降低复杂度. 那么我们假设k<j,当i出现之后,k就不可能作为答案,那么这些k在i处满足的性质就是 dp[j]+(s[i]-s[j])^2+m<=dp[k]+(s[i]-s