标签:return int 队头 HDU3507 k2 k1 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
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。