• Print Article /// 斜率优化DP oj26302


    题目大意:

    典题

    数学分析 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 ",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--;
    */
  • 相关阅读:
    python 匿名函数lambda()
    python列表推导式
    python数组的基本操作一(添加,扩展,插入)
    Python的数字类型
    Python初识以及Windows安装教程
    字典简单使用
    two sum(LeetCode)
    python读写文件
    C++ volatile关键字(转)
    实验一
  • 原文地址:https://www.cnblogs.com/zquzjx/p/9162040.html
Copyright © 2020-2023  润新知