• hdu 3507 Print Article (DP, Monotone Queue)


    斜率优化的DP,完全是看资料做出来的。下面给出资料中对两个结论的证明:

    对基本公式f[i]=min{f[j]+(s[i]-s[j])^2+M},取i的两个一般决策点j,k(j<k),s[i]为1..i的cost总和,因为cost非负,所以s随i不减。

    若k优于j,则f[k]+(s[i]-s[k])^2+M<f[j]+(s[i]-s[j])^2+M,化简得f[k]-f[j]+s[k]^2-s[j]^2<2*s[i]*(s[k]-s[j])。

    由于j<k,则s[k]>s[j],两边同除s[k]-s[j]得(f[k]-f[j]+s[k]^2-s[j]^2)/(s[k]-s[j])<2*s[i]。 

    方便起见,我们将左边分式的分子分母同时变号(f[j]-f[k]+s[j]^2-s[k]^2)/(s[j]-s[k])<2*s[i]。

     

    可以看到不等式左边与i无关,右边只与i有关。 记slope[j,k]=(f[j]-f[k]+s[j]^2-s[k]^2)/(s[j]-s[k])。

    结论1:

    对于i的两个决策点j,k(j<k),决策k优于决策j就等价于slope[j,k]<2*s[i]。

    其实我们还可以知道,决策点k永远会比决策点j优,因为对于以后的i',s[i']>s[i]>slope[j,k]。

    再来考虑三个点j,k,l(j<k<l)之间的优劣关系。

    还是通过斜率:
    如果slope[j,k]>slope[k,l]:
    1.若slope[k,l]<2*s[i],那么由之前的结论1,l 比k优。
    2.若slope[k,l]>2*s[i],则slope[j,k]>2*s[i],那么由之前的结论(△),决策j不比k差。
    综上,如果slope[j,k]>slope[k,l],k是可以淘汰掉的。
    结论2:
    对于三个决策点j,k,l(j<k<l),如果slope[j,k]>slope[k,l],那么k永远不会成为某个点的最优决策。

    根据这两个结论,用一个单调队列来剔除无用决策。

    code:

    #include<cstdio>
    long long dp[500001] ;
    int queue[500001] ;
    long long sum[500001] ;
    int slope(int j, int k){
        if(sum[j]==sum[k])
            if(dp[j]>dp[k]) return -1 ;
            else    return 2147483647 ;
        return (dp[j]-dp[k]+sum[j]*sum[j]-sum[k]*sum[k])/(sum[j]-sum[k]) ;
    }
    int main(){
        int n, m, h, r ;
        while(~scanf("%d%d", &n, &m)){
            sum[0] = 0 ;
            for(int i=1; i<=n; i++){
                scanf("%lld", &sum[i]) ;
                sum[i] += sum[i-1] ;
            }
            h = r = 0 ;
            for(int i=1; i<=n; i++){
                while(h<r&&slope(queue[h], queue[h+1])<2*sum[i])  h ++ ;//结论1
                dp[i] = dp[queue[h]] + (sum[i]-sum[queue[h]]) * (sum[i]-sum[queue[h]]) + m ;
                while(h<r&&slope(queue[r-1], queue[r])>slope(queue[r], i))  r -- ;//结论2
                r ++ ;
                queue[r] = i ;
            }
            printf("%lld\n", dp[n]) ;
        }
        return 0 ;

    }


  • 相关阅读:
    flex 鼠标事件和效果
    查看和修改Oracle服务器端的字符集
    Oracle随机抽取数据sql
    hibernate.properties
    Oracle11g物理文件冷备份(转)
    支付宝接口使用文档说明 支付宝异步通知(notify_url)与return_url
    关于Oracle的行转列
    Intellij idea 12 tomcat日志窗口不显示问题
    在Servlet中获取来源URL
    uniapp 实现小程序列表项左滑菜单
  • 原文地址:https://www.cnblogs.com/xiaolongchase/p/2344769.html
Copyright © 2020-2023  润新知