• TYVJ 1215 斜率优化DP


    题目连接:http://new.tyvj.cn/Problem_Show.aspx?id=1215

    思路:

    方程再简单不过了:

    dp[i]表示以第i个人为某一组最后一个人的总战斗值

    dp[i]=max(dp[j]+F(sum[i]-sum[j]))

    其中F(x)=A*x*x+B*x+C       sum[i]表示战斗值的前缀和

    显然n^2的方程,只能得到20分

    单调性显然,那么就开始我们的斜率优化

    设j<k且满足k比j更优

    dp[j]+A*(sum[i]-sum[j])^2+B*(sum[i]-sum[j])+C<=dp[k]+A*(sum[i]-sum[k])^2+B*(sum[i]-sum[k])+C

    化简,分离变量,将含j,k的结构放到方程一边,含i的结构放在方程另一边:

    2*A*sum[i]*(sum[k]-sum[j])<=dp[k]-dp[j]+B*(sum[j]-sum[k])+A*(sum[k]^2-sum[j]^2)

    设:

    p[i]=2*A*sum[i]

    G(k,j)=dp[k]-dp[j]+B*(sum[j]-sum[k])+A*(sum[k]^2-sum[j]^2)

    S(k,j)=sum[k]-sum[j]

    W(k,j)=G(k,j)/S(k,j)

    所以只要维护   :   W(k,j)>=p[i]   就可以了~

    (PS:如果没有看懂斜率优化,请转步:http://www.cnblogs.com/proverbs/archive/2012/10/06/2713109.html

    View Code
     1 #include <cstdio>
     2 #include <cstring>
     3 #include <cstdlib>
     4 #include <iostream>
     5 
     6 #define N 1001000
     7 
     8 using namespace std;
     9 
    10 __int64 A,B,C,a[N],sum[N],dp[N],p[N];
    11 int n,q[N];
    12 
    13 void read()
    14 {
    15     scanf("%d",&n);
    16     scanf("%I64d%I64d%I64d",&A,&B,&C);
    17     for(int i=1;i<=n;i++)
    18     {
    19         scanf("%I64d",&a[i]);
    20         sum[i]=sum[i-1]+a[i];
    21         p[i]=2*A*sum[i];
    22     }
    23 }
    24 
    25 inline __int64 G(int y,int x)
    26 {
    27     return dp[y]-dp[x]+B*(sum[x]-sum[y])+A*(sum[y]*sum[y]-sum[x]*sum[x]);
    28 }
    29 
    30 inline __int64 S(int y,int x)
    31 {
    32     return sum[y]-sum[x];
    33 }
    34 
    35 inline __int64 F(int x)
    36 {
    37     return A*x*x+B*x+C;
    38 }
    39 
    40 void go()
    41 {
    42     dp[0]=0;
    43     int h=1,t=1;
    44     q[t++]=0;
    45     for(int i=1,x,y,z;i<=n;i++)
    46     {
    47         while(h<t-1&&G(q[h+1],q[h])>=p[i]*S(q[h+1],q[h])) h++;
    48         
    49         dp[i]=dp[q[h]]+F(sum[i]-sum[q[h]]);
    50         
    51         q[t++]=i;
    52         
    53         for(int j=t-2;j-1>=h;j--)
    54         {
    55             x=q[j-1]; y=q[j]; z=q[j+1];
    56             if(G(z,y)*S(y,x)>=G(y,x)*S(z,y)) q[j]=q[--t];
    57             else break;
    58         }
    59     }
    60     printf("%I64d\n",dp[n]);
    61 }
    62 
    63 int main()
    64 {
    65     read();
    66     go();
    67     return 0;
    68 }
    没有人能阻止我前进的步伐,除了我自己!
  • 相关阅读:
    leetcode78 Subsets
    leetcode76 Minimum Window Substring
    leetcode73 Set Matrix Zeroes
    leetcode70 Climbing Stairs
    leetcode50 Pow(x, n)
    leetcode49 Group Anagrams
    leetcode48 Rotate Image
    正则表达式及字符处理
    RPM软件包管理.作业
    yum管理RPM包.作业
  • 原文地址:https://www.cnblogs.com/proverbs/p/2713293.html
Copyright © 2020-2023  润新知