码迷,mamicode.com
首页 > 其他好文 > 详细

Print Article /// 斜率优化DP oj26302

时间:2018-06-10 11:40:16      阅读:133      评论:0      收藏:0      [点我收藏+]

标签:hdu   define   IV   pre   archive   php   pac   bsp   using   

题目大意:

典题

数学分析 G(a,b)<sum[i]时 a优于b

G(a,b)<G(b,c)<sum[i]时 b必不为最优

#include <bits/stdc++.h>
#define N 500005
using namespace std;
int n,m,dp[N],deq[N],sum[N]; 
// deq[]为单调队列 sum[]为数组的前缀和
int DP(int i,int j) { return dp[j]+m+(sum[i]-sum[j])*(sum[i]-sum[j]); } int UP(int j,int k) { //yj-yk的部分 return dp[j]+sum[j]*sum[j]-(dp[k]+sum[k]*sum[k]); } int DOWN(int j,int k) {//xj-xk的部分 return 2*(sum[j]-sum[k]); } /* 由分析 当0<a<b<i时 若(ya-yb)/(xa-xb)<sum[i] 此处表达为G(a,b)<sum[i] 则j优于k 若存在a,b和b,c满足上述要求 即存在G(a,b)<sum[i] G(b,c)<sum[i] 若G(a,b)<G(b,c) 则b肯定不为最优点 */ int main() { while(~scanf("%d%d",&n,&m)) { sum[0]=dp[0]=0; for(int i=1;i<=n;i++) { int num; scanf("%d",&num); sum[i]=sum[i-1]+num; } int head=0, tail=0; deq[tail++]=0; for(int i=1;i<=n;i++) { while(head+1<tail && UP(deq[head+1],deq[head])<=sum[i] *DOWN(deq[head+1],deq[head])) head++; /// G(head+1,head)<=sum[i] 即head+1优于head 则去掉head dp[i]=DP(i,deq[head]); // 用此时的最优head更新dp[i] while(head+1<tail && UP(i,deq[tail-1])*DOWN(deq[tail-1],deq[tail-2]) <=DOWN(i,deq[tail-1])*UP(deq[tail-1],deq[tail-2])) tail--; /// 如果此时G(i,tail-1)<=G(tail-1,tail-2)<=sum[i] 则说明tail-1对应点为可删去 deq[tail++]=i; } printf("%d\n",dp[n]); } return 0; }
/*
纠结了一下维护单调队列时为什么判断条件是<=
第一处
G(head+1,head)=sum[i] 说明 两者平等 不存在谁更优这个问题
而仍然 head++; 是因为既然两者平等 那么只要留一个就可以了
第二处 G(i,tail-1)=G(tail-1,tail-2) 说明 两者斜率相等
即 i,tail-1,tail-2 三个对应点在同一条直线上
那么 tail-1 这个点可以直接忽略 所以继续 tail--;
*/

 

Print Article /// 斜率优化DP oj26302

标签:hdu   define   IV   pre   archive   php   pac   bsp   using   

原文地址:https://www.cnblogs.com/zquzjx/p/9162040.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!