其他分享
首页 > 其他分享> > HDU3507 print article (斜率优化DP)

HDU3507 print article (斜率优化DP)

作者:互联网

状态表示:dp[i]表示打印前i个单词的最小成本;s[i]维护前缀和。

状态转移:dp[i]=min(dp[j]+(s[i]-s[j])2)+m , 0<=j<i。

换成y=kx+b的形式:dp[j]+s[j]2=2*s[i]*s[j]+dp[i]-s[i]2-m。

算法步骤:1.枚举i=1...n,k=2*s[i]。

2.检查单调队列队头,排除决策.。

3.此时队头就是最优决策j,根据方程计算dp[i]。

4.加入新决策i,检查下凸性,删除队尾直至满足下凸性。

5.最优解为dp[n]。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=5e5+10;
 4 int dp[N],s[N],q[N];
 5 int n,m;
 6 
 7 int GetY(int k1,int k2){//求y得差值 
 8     return dp[k2]+s[k2]*s[k2]-(dp[k1]+s[k1]*s[k1]);
 9 }
10 
11 int GetX(int k1,int k2){//求x的差值 
12     return s[k2]-s[k1];
13 }
14 
15 int GetVal(int i,int j){//得到dp[i]的值 
16     return dp[j]+(s[i]-s[j])*(s[i]-s[j])+m;
17 }
18 
19 int main(){
20     while(~scanf("%d%d",&n,&m)){
21         s[0]=0;
22         dp[0]=0;
23         for(int i=1;i<=n;i++){
24             scanf("%d",&s[i]);
25             s[i]+=s[i-1];
26         }
27         int head=0,tail=0;
28         q[tail++]=0;//单调队列 ,该队列要维护斜率单增 
29         for(int i=1;i<=n;i++){
30             while(head+1<tail && GetY(q[head],q[head+1])<=2*s[i]*GetX(q[head],q[head+1]))
31                 head++;//排除之前的不是最优的决策 
32             dp[i]=GetVal(i,q[head]);
33             
34             while(head+1<tail && GetY(q[tail-1],i)*GetX(q[tail-2],q[tail-1])<=GetY(q[tail-2],q[tail-1])*GetX(q[tail-1],i))
35                 tail--;//维护下凸包,不满足则删去 
36             q[tail++]=i;
37         }
38         printf("%d\n",dp[n]);
39     }
40     return 0;
41 }

 

标签:return,int,队头,HDU3507,k2,k1,print,article,dp
来源: https://www.cnblogs.com/yhxnoerror/p/16365830.html