hdu3507 Print Article DP+斜率优化

点击打开链接

题意:就是给一个序列,让你分成很多段,每段按照题目的公式算出答案,要所有的答案加起来最小


思路一:(参考)http://www.cnblogs.com/lidaxin/p/5116577.html

斜率优化。
设f[i]表示前i个数分段后的最小值,则转移式为f[i]=min{f[j]+(sum[i]-sum[j])^2+M},1<=j<i
进一步得:f[i]=min{ (f[j]+sum[j]^2-2*sum[i]*sum[j])+(sum[i]^2+M) }

设y(j)=f[j]+sum[j]^2,a[i]=sum[i],x(j)=sum(j),则f[i]=min{y(j)-2*a[i]*x(j)}+sum[i]^2+M

则要求min p=y+2ax , 单调队列维护下凸包。


1 while(L<R && q[L+1].y-2*sum[i]*q[L+1].x <= q[L].y-2*sum[i]*q[L].x) L++;
2 now.x = sum[i];
3 now.y = q[L].y-2*sum[i]*q[L].x+2*sum[i]*sum[i]+m;
4 while(L<R && cross(q[R-1],q[R],now)<=0) R--;
5 q[++R] = now;
now.y = y[i] = f[i]+sum[j]^2 = min{ (f[j]+sum[j]^2-2*sum[i]*sum[j])+(sum[i]^2+M) } + sum[i]^2

答案就是  y[n]=q[R].y=f[n]+sum[n]^2  ==>  q[R].y-sum[n]^2; 

代码一:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 #define mem(a) memset(a,0,sizeof(a))
 5 #define mp(x,y) make_pair(x,y)
 6 const int maxn = 5e5+10;
 7 const int INF = 0x3f3f3f3f;
 8 const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
 9 inline ll read(){
10     ll x=0,f=1;char ch=getchar();
11     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
12     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
13     return x*f;
14 }
15 //////////////////////////////////////////////////////////////////////////
16 int n,m,a;
17 int sum[maxn];
18 
19 struct node{
20     int x,y;
21 }now,q[maxn];
22 
23 int cross(node A,node B,node sum){
24     return (B.x-A.x)*(sum.y-A.y) - (sum.x-A.x)*(B.y-A.y);
25 }
26 
27 int main(){
28     while(scanf("%d%d",&n,&m)==2){
29         mem(sum);
30         for(int i=1; i<=n; i++){
31             scanf("%d",&a);
32             sum[i] = sum[i-1]+a;
33         }
34 
35         int L=0,R=0;
36         for(int i=1; i<=n; i++){
37             while(L<R && q[L+1].y-2*sum[i]*q[L+1].x <= q[L].y-2*sum[i]*q[L].x) L++;
38             now.x = sum[i];
39             now.y = q[L].y-2*sum[i]*q[L].x+2*sum[i]*sum[i]+m;
40             while(L<R && cross(q[R-1],q[R],now)<=0) R--;
41             q[++R] = now;
42         }
43 
44         printf("%d
",q[R].y-sum[n]*sum[n]);
45     }
46 
47     return 0;
48 }


思路二: 参考:http://www.cnblogs.com/kuangbin/archive/2012/08/26/2657650.html

kuangbin大神= = 非常详细

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 #define mem(a) memset(a,0,sizeof(a))
 5 #define mp(x,y) make_pair(x,y)
 6 const int maxn = 5e5+10;
 7 const int INF = 0x3f3f3f3f;
 8 const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
 9 inline ll read(){
10     ll x=0,f=1;char ch=getchar();
11     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
12     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
13     return x*f;
14 }
15 //////////////////////////////////////////////////////////////////////////
16 
17 int n,m;
18 int sum[maxn],f[maxn],q[maxn];
19 
20 // int slope(int j,int k){ // WA!!! 
21 //     return ((double)(f[j]+sum[j]*sum[j]-(f[k]+sum[k]*sum[k]))) / ((double)(2*(sum[j]-sum[k])));
22 // }
23 
24 int getUP(int j,int k)
25 {
26     return f[j]+sum[j]*sum[j]-(f[k]+sum[k]*sum[k]);
27 }
28 int getDOWN(int j,int  k)
29 {
30     return 2*(sum[j]-sum[k]);
31 }
32 
33 int main(){
34     //f[i]=min((sum[i]-sum[j])^2+m+f[j])
35     while(scanf("%d%d",&n,&m)==2){
36         sum[0],f[0]=0;q[0]=0;
37         for(int i=1; i<=n; i++){
38             int a; scanf("%d",&a);
39             sum[i] = sum[i-1]+a;
40         }
41 
42         int L=0,R=0;
43         for(int i=1; i<=n; i++){
44             while(L<R && getUP(q[L+1],q[L]) <= sum[i]*getDOWN(q[L+1],q[L])) 
45                 L++;
46             int j = q[L];
47             f[i] = f[j] + (sum[i]-sum[j])*(sum[i]-sum[j]) + m;
48             while(L<R && (getUP(i,q[R])*getDOWN(q[R],q[R-1]) <= getUP(q[R],q[R-1])*getDOWN(i,q[R]))) 
49                 R--;
50             q[++R] = i;
51         }
52 
53         // int L=0,R=0;
54         // for(int i=1; i<=n; i++){
55         //     while(L<R && slope(q[L+1],q[L]) <= sum[i]) L++;
56         //     int j = q[L];
57         //     f[i] = f[j] + (sum[i]-sum[j])*(sum[i]-sum[j]) + m;
58         //     while(L<R && slope(i,q[R]) <= slope(q[R],q[R-1])) R--;
59         //     q[++R] = i;
60         // }
61         printf("%d
",f[n]);
62     }
63 
64     return 0;
65 }
原文地址:https://www.cnblogs.com/yxg123123/p/6827710.html