HDU 3507斜率优化dp

Print Article

Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)
Total Submission(s): 12185    Accepted Submission(s): 3733

Problem Description

Zero has an old printer that doesn‘t work well sometimes. As it is antique, he still like to use it to print articles. But it is too old to work for a long time and it will certainly wear and tear, so Zero use a cost to evaluate this degree.
One day Zero want to print an article which has N words, and each word i has a cost Ci to be printed. Also, Zero know that print k words in one line will cost

M is a const number.
Now Zero want to know the minimum cost in order to arrange the article perfectly.

Input

There are many test cases. For each test case, There are two numbers N and M in the first line (0 ≤ n ≤ 500000, 0 ≤ M ≤ 1000). Then, there are N numbers in the next 2 to N + 1 lines. Input are terminated by EOF.

Output

A single number, meaning the mininum cost to print the article.

Sample Input

5 5

5
9
5
7
5

Sample Output

230

Author

Xnozero

Source

2010 ACM-ICPC Multi-University Training Contest(7)——Host by HIT

题意:

有n个字,每个字有权值a[i],要打印第j到第i之间的字要花费sum(a[i]~a[j])+m的费用,求最少花费。

输入n,m

输入n个数的a[i]

代码:

//和上一个题一样,dp[i]=min(dp[j]+m+(sum[i]-sum[j])^2)
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int maxn=500009;
int n,m,que[maxn];
ll sum[maxn],dp[maxn];
ll getdp(int i,int j){
    return dp[j]+m+(sum[i]-sum[j])*(sum[i]-sum[j]);
}
ll getup(int j,int k){
    return dp[j]-dp[k]+sum[j]*sum[j]-sum[k]*sum[k];
}
ll getlow(int j,int k){
    return 2*(sum[j]-sum[k]);
}
int main()
{
    while(scanf("%d%d",&n,&m)==2){
        sum[0]=0;
        for(int i=1;i<=n;i++){
            scanf("%lld",&sum[i]);
            sum[i]+=sum[i-1];
        }
        int head=0,tail=0;
        que[tail++]=0;
        for(int i=1;i<=n;i++){
            while(head+1<tail&&getup(que[head+1],que[head])<sum[i]*getlow(que[head+1],que[head]))
                head++;
            dp[i]=getdp(i,que[head]);
            while(head+1<tail&&getup(que[tail-1],que[tail-2])*getlow(i,que[tail-1])>=getup(i,que[tail-1])*getlow(que[tail-1],que[tail-2]))
                tail--;
            que[tail++]=i;
        }
        printf("%lld\n",dp[n]);
    }
    return 0;
}
时间: 2024-11-07 20:39:32

HDU 3507斜率优化dp的相关文章

HDU 3507(斜率优化dp

题目:每次选取连续的若干数字的代价 要求选取虽有数字的最小代价. 思路:基础斜率dp题,题解见http://www.cnblogs.com/kuangbin/archive/2012/08/26/2657650.html /* * @author: Cwind */ #pragma comment(linker, "/STACK:102400000,102400000") #include <iostream> #include <map> #include &

hdu 3507 斜率优化

我的第一道斜率优化. 就这道题而言,写出原始的方程: dp[i] = min{ dp[j] + (sum[i]-sum[j])2  + M | j in [0,i) } O(n^2)的复杂度肯定超时,要么优化转移,要么重写方程. 斜率优化的思想就是减少不必要的枚举(即不枚举肯定不会成为决策点的j). 我们考虑两个位置p<q<i “选择q比选择p优” 当且仅当 dp[q]+(sum[i]-sum[q])2+M < dp[p]+(sum[i]-sum[p])2+M 化简右边即: [ (dp[

hdu 3669(斜率优化DP)

Cross the Wall Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 327680/327680 K (Java/Others)Total Submission(s): 4479    Accepted Submission(s): 812 Problem Description “Across the Great Wall, we can reach every corner in the world!” Now the

Fxx and game hdu 5945 斜率优化dp

dfs你怕是要爆炸 考虑dp; 很容易想到 dp[ i ] 表示到 i 时的最少转移步数: 那么: dp[ i ]= min( dp[ i ],dp[ i-j ]+1 ); 其中 i-t<=j<=i; 当 i%k==0时 ,dp[ i ]=min( dp[ i ],dp[ i/k ]+1 ): 很明显这种要T到飞起: 我们要优化dp: 1e6的数据考虑O(n)级别的: 斜率优化: #include<iostream> #include<cstdio> #include&

HDU 4258 斜率优化dp

Covered Walkway Time Limit: 30000/10000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 1496    Accepted Submission(s): 602 Problem Description Your university wants to build a new walkway, and they want at least p

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

hdu 3507 斜率dp

不好理解,先多做几个再看 此题是很基础的斜率DP的入门题. 题意很清楚,就是输出序列a[n],每连续输出的费用是连续输出的数字和的平方加上常数M 让我们求这个费用的最小值. 设dp[i]表示输出前i个的最小费用,那么有如下的DP方程: dp[i]= min{ dp[j]+(sum[i]-sum[j])^2 +M }  0<j<i 其中 sum[i]表示数字的前i项和. 相信都能理解上面的方程. 直接求解上面的方程的话复杂度是O(n^2) 对于500000的规模显然是超时的.下面讲解下如何用斜率

hdu 2993 MAX Average Problem (斜率优化dp入门)

MAX Average Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5855    Accepted Submission(s): 1456 Problem Description Consider a simple sequence which only contains positive integers as