zoukankan      html  css  js  c++  java
  • bzoj 1911 特别行动队

    题意:将 n 个人分组,分组后,一个组的战斗力等于 a*sum*sum + b*sum + c,怎么分组使得战斗力和最大。

    分析:

    第一次自己从头到尾推出来的斜率DP。

    状态定义 d[i] : 前 i 个人分组得到的最优值。

    状态转移 d[i] =  max (  d[j]  + a*(sum[i] - sum[j])^2 +b*(sum[i] - sum[j])  +c   )

    显然是O(n^2)

    假设 k < j < i ; j 决策点更优。

     这个斜率公式比较复杂了,其实就是将分子,分母转为 与 j 和 k 有关的斜率式子,另一边不能有关于 j 和 k 。

    有了这个斜率公式,接下来就是分析斜率递增还是递减了。

    假设3个决策点 k < j < i

    显然 凸多边形,j 点不是最优点,不可能存在凸点。

    然后就是根据多边形的性质,相切之前怎么样,加入之后删点等... ...

    #include<bits/stdc++.h>
    
    using namespace std;
    const int maxn = 1e6+5;
    
    int n;
    long long a,b,c;
    long long x;
    long long sum[maxn];
    long long d[maxn];
    double slope(int i,int j)
    {
        double up = d[i]-d[j]+a*(sum[i]*sum[i]-sum[j]*sum[j])+b*(sum[j]-sum[i]);
        double down = 2*a*(sum[i]-sum[j]);
        return up/down;
    }
    int l,r,q[maxn];
    
    int main()
    {
        scanf("%d",&n);
        scanf("%lld%lld%lld",&a,&b,&c);
        long long x;
        for(int i = 1; i <= n; i++) {
    
            scanf("%lld",&x);
            sum[i] = sum[i-1] + x;
        }
    
        for(int i=1;i<=n;i++)
        {
            while(l<r&&slope(q[l],q[l+1])<sum[i])l++;
            int now = q[l];
            d[i]=d[now]+a*(sum[i]-sum[now])*(sum[i]-sum[now])+b*(sum[i]-sum[now])+c;
            while(l<r&&slope(q[r-1],q[r])>slope(q[r],i))r--;
            q[++r]=i;
        }
        printf("%lld
    ",d[n]);
    
        return 0;
    }
    View Code
  • 相关阅读:
    关于排序--sort()和qsort()使用
    UVA--147 Dollars(完全背包)
    UVA--674 Coin Change(完全背包)
    HDU--1203 I NEED A OFFER!(01背包)
    编程中关于无穷大的设定技巧
    HDU--2126 Buy the souvenirs(二维01背包)
    HDU--2639 Bone Collector II(01背包)
    MySQL中的group_concat函数
    Redis监控
    JAVA中的代理模式
  • 原文地址:https://www.cnblogs.com/TreeDream/p/7487142.html
Copyright © 2011-2022 走看看