hdu3507

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.

InputThere 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.OutputA single number, meaning the mininum cost to print the article.Sample Input

5 5
5
9
5
7
5

Sample Output

230这是一道斜率优化的模板题吧。斜率优化算是真的弄懂了个大概,不然第一次听的时候什么也不会。就是开头就是判断一个条件,不断取出头,保证最优,队列中的就是满足1比2优,2比3优,这样,因为后者进入的时间迟,所以又可以成为最优解,我注释了很多。
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<cstring>
 6
 7 typedef long long LL;
 8 using namespace std;
 9
10 const int NN=500007;
11
12 int n,m;
13 int dp[NN],sum[NN],q[NN];
14
15 int GetY(int i,int j)
16 {
17     return sum[i]*sum[i]+dp[i]-(sum[j]*sum[j]+dp[j]);
18 }
19
20 int GetX(int i,int j)
21 {
22     return 2*(sum[i]-sum[j]);
23 }
24
25 int main()
26 {
27     int x;
28     while(~scanf("%d%d",&n,&m))
29     {
30         int head=0,tail=0;
31         q[tail++]=0;//这一步必须,因为可能前i个数全部作为一段才是最小值
32         for(int i=1;i<=n;i++)
33         {
34             scanf("%d",&x);
35             sum[i]=sum[i-1]+x;
36             while(head+1<tail&&GetY(q[head+1],q[head])<=GetX(q[head+1],q[head])*sum[i])
37                 head++;//更新最优的点
38             dp[i]=(sum[i]-sum[q[head]])*(sum[i]-sum[q[head]])+m+dp[q[head]];//计算dp[i]的最小值
39             while(head+1<tail&&GetY(i,q[tail-1])*GetX(q[tail-1],q[tail-2])<=GetY(q[tail-1],q[tail-2])*GetX(i,q[tail-1]))
40                 tail--;//以k,j,i为判断斜率,然后去掉j。
41             q[tail++]=i;
42         }
43         printf("%d\n",dp[n]);
44     }
45 }  
时间: 2024-10-19 18:03:49

hdu3507的相关文章

hdu3507之斜率优化DP入门

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

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(斜率优化入门)(pascal)

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 t

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

【HDU3507】Print Article

单调队列DP复出练手题 朴素方程dp[i]=min(dp[j]+(s[i]-s[j-1])^2+m 你懂得 1 var dp,s:array[0..500000]of int64; 2 a,q:array[1..500000]of longint; 3 n,m,i,t,w:longint; 4 5 function sum(x,y:longint):int64; 6 begin 7 exit(s[y]-s[x-1]); 8 end; 9 10 function clac(j,i:longint)

[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 artical

题目大意:有N个数字a[N],每输出连续的一串,它的费用是 “这行数字的平方加上一个常数M”.问如何输出使得总费用最小.(n<=500000) 分析:动态规划方程为:dp[i]=dp[j]+M+(sum[i]-sum[j])^2: 右边有一项为:sum[i]*sum[j].考虑用单调队列. 令dp[i]=g,dp[j]+M+sum[i]^2+sum[j]^2=y,sum[j]=y,2*sum[i]=k 则上式变为g=y-kx,即y=kx+g.此为直线方程. 我们要使得g最小,即可以考虑有一条斜率

HDU3507 Print Article

Print Article Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others) 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 to

斜率优化第一题! HDU3507 | 单调队列优化DP

放一手原题 题解: 第一次写(抄)斜率优化,心里还是有点小激动的.讲一下怎么实现的! 首先我们可以考虑一个朴素的dp:DP[i]表示前i个数字的最少花费,显然我们有一个转移方程 DP[i]=min{DP[j]+M+(sum[i]-sum[j])^2} 但是N^2肯定会超时,我们考虑优化他 假设有k<j<i,如果令j对i的贡献比k好 显然我们有这样的式子 DP[j]+M+(sum[i]-sum[j])^2 < DP[k]+M+(sum[i]-sum[j])^2 把平方打开之后移项 可以得到