zoukankan      html  css  js  c++  java
  • 【BZOJ1010】【HNOI2008】玩具装箱toy (斜率优化DP) 解题报告

    题目:

    题目在这里

    思路与做法:

    这题不难想。

    首先我们先推出一个普通的dp方程:

    (f_i = min { f_j+(i-j-1+sum_i-sum_j-L)^2})

    然后就推一推式子了:

    我们来比较计算f[i]时的j和k两个决策

    (f_j+(i-j-1+sum_i-sum_j-L)^2 < f_k+(i-k-1+sum_i-sum_k-L)^2)

    (num_i = i+sum_i)

    (C = L+1)

    (f_j+(num_i-num_j-L-1)^2 < f_k+(num_i-num_j-L-1)^2)

    (f_j+{num_i}^2-2*num_i*(num_j+C)+(num_j+C)^2)
    (<f_k+{num_i}^2-2*num_i*(num_k+C)+(num_k+C)^2)

    $f_j+(num_j+C)2-f_k-(num_k+C)2 < $
    (2*num_i*(num_j-num_k))

    ({f_j+(num_j+C)^2-f_k-(num_k+C)^2 over 2*(num_j-num_k)} < num_i)

    接下来就可以用斜率优化dp了。

    代码:

    #include <iostream>
    #include <cstdlib>
    #include <cstdio>
    #include <cstring>
    
    using namespace std;
    
    const int N = 50010;
    
    inline long long sqr(long long x) { return x*x; }
    
    long long a[N];
    
    long long sum[N];
    
    long long num[N], C;
    
    long long f[N];
    double calc(int j, int k) { return (double)(f[j]+sqr(num[j]+C)-f[k]-sqr(num[k]+C))/(double)(2*(num[j]-num[k])); }
    int Q[N], hd, tl;
    
    int main()
    {   int n;
    	long long m;
    	scanf("%d%lld", &n, &m);
    	for(int i=1; i<=n; i++)
    	{   scanf("%lld", &a[i]);
    		sum[i] = sum[i-1]+a[i];
    	}
    	for(int i=1; i<=n; i++) num[i] = sum[i]+i;
    	C = m+1;
    	Q[hd = 0] = 0;
    	tl = 1;
    	for(int i=1; i<=n; i++)
    	{   while(hd < tl-1 && calc(Q[hd+1], Q[hd]) <= num[i]) hd++;
    		f[i] = f[Q[hd]] + sqr(num[i]-num[Q[hd]]-C);
    		while(hd < tl-1 && calc(i, Q[tl-1]) <= calc(Q[tl-1], Q[tl-2])) tl--;
    		Q[tl++] = i;
    	}
    	printf("%lld
    ", f[n]);
    	return 0;
    }
    
  • 相关阅读:
    Asp.net 主题 【2】
    Asp.net 主题 【1】
    登陆验证码
    Ajax进阶
    Ajax
    Django之权限管理
    Django之Form进阶
    Django之知识总结
    Django之form表单认证
    Django之ORM查询复习与cookie
  • 原文地址:https://www.cnblogs.com/2016gdgzoi509/p/8591939.html
Copyright © 2011-2022 走看看