首页 > 其他分享 >P3195 [HNOI2008]玩具装箱

P3195 [HNOI2008]玩具装箱

时间:2023-01-21 18:00:10浏览次数:51  
标签:P3195 元素 j1 j2 斜率 dp HNOI2008 装箱 单调

题目:P3195 [HNOI2008]玩具装箱 

一道斜率优化dp题。

先考虑状态和转移方程:

令$dp[i]$表示装前$i$个玩具所需要最小花费,$j$表示上一个容器右端点,$sum[i]$表示前$i$个玩具长度之和,则可得到转移方程为: $$ dp[i]=\min_{0 \le j<i}\ dp[j] +(\ i-j-1+sum[i]-sum[j]-L\ )^2\ $$ 又令$\ f[i]=sum[i]+i \ $继续简化方程为: $$ dp[i]=\min_{0 \leq j<i}\ dp[j]+(\ f[i]-f[j]-(\ L+1\ )\ )^2 $$

但显然这样复杂度是$O(n^2)$的,对于$n\le5e4$是无法通过的。

再考虑优化:

对于$dp[i]$是由最优的$j$转移过来,假设现在有两个决策$j1,j2(0 \le j1<j2<i)$且$j2$优于$j1$,则有: $$ dp[j1]+(f[i]-f[j1]-(L+1))^2 \ge dp[j2]+(f[i]-f[j2]-(L+1))^2 $$ 拆开可得: $$ dp[j1]-2\times f[i]\times (f[j1]+L+1)+(f[j1]+L+1)^2 \ge dp[j2]-2\times f[i]\times (f[j2]+L+1)+(f[j2]+L+1)^2 $$ $$ 2\times f[i]\times (f[j2]-f[j1]) \ge dp[j2]+(f[j2]+L+1)^2-dp[j1]-(f[j1]+L+1)^2 $$ 令$g[i]=(f[i]+L+1)^2\ $则有: $$ 2\times f[i]\times (f[j2]-f[j1])\ge dp[j2]+g[j2]-dp[j1]-g[j1]$$ $$ 2\times f[i]\ge \frac{dp[j2]+g[j2]-dp[[j1]-g[j1]}{f[j2]-f[j1]} \\ $$若$j1,j2$满足上面这个式子,那么$j2$一定优于$j1$。观察发现,两两决策间的斜率是单调上升的。 因为:

 

发现上图中$j2$不可能是一个最优决策,当$2\times f[i]$小于$j1,j2$的斜率时,$j1$显然优于$j2$,而当$2\times f[i]$大于等于$j1,j2$斜率时,显然$j2,j3$的斜率更小也满足$j3$优于$j2$,所以$j2$不可能最优,也就是两两决策间斜率单调上升(也就是一个下凸壳)。

又因为这道题$f[i]$是单调上升的,所以我们可以用单调队列来维护。具体实现:把决策放进一个单调队列里,如果队首元素和第二个元素间的斜率小于等于当前的$2\times f[i]$,我们就把队首元素弹出(因为他不优),这样每次更新$i$时就用处理过后的单调队列队首元素即可。再向单调队列里加入$i$,如果发现加入$i$后队尾元素两两间斜率不满足单调上升,我们就先把队尾元素弹出,直到满足但满足单调上升后,再将$i$入队。

复杂度:$O(n)$

代码:

 1 #include <bits/stdc++.h>
 2 
 3 #define int long long 
 4 
 5 using namespace std;
 6 
 7 int read(){
 8     int x=0,fl=1;
 9     char c=getchar();
10     while(!isdigit(c)){if(c=='-') fl=-1;c=getchar();}
11     while(isdigit(c)) x=(x<<1)+(x<<3)+(c^48),c=getchar();
12     return x*fl;
13 }
14 
15 const int N=5e4+5;
16 
17 int n,L;
18 int c[N],sum[N],f[N],g[N];
19 int dp[N];
20 int q[N],head,tail;
21 
22 double check(int j1,int j2){
23     return (double)(dp[j2]+g[j2]-dp[j1]-g[j1])/(f[j2]-f[j1]);
24 }
25 
26 signed main(){
27     n=read(),L=read();
28     for(int i=1;i<=n;++i){
29         c[i]=read();
30         sum[i]=sum[i-1]+c[i];
31         f[i]=sum[i]+i;
32         g[i]=(f[i]+L+1)*(f[i]+L+1);
33     }
34     g[0]=(L+1)*(L+1);
35     for(int i=1;i<=n;++i){
36         while(head<tail&&check(q[head],q[head+1])<=2*f[i]) ++head;//队首元素不优,弹出队首元素 
37         dp[i]=dp[q[head]]+(f[i]-f[q[head]]-L-1)*(f[i]-f[q[head]]-L-1);//更新dp值
38         while(head<tail&&check(q[tail],i)<check(q[tail-1],q[tail])) --tail;
39         q[++tail]=i; 
40     }
41     cout<<dp[n]<<'\n';
42     return 0;
43 } 

 

标签:P3195,元素,j1,j2,斜率,dp,HNOI2008,装箱,单调
From: https://www.cnblogs.com/qazxswedc123/p/17063952.html

相关文章

  • P3193 [HNOI2008]GT考试
    先考虑朴素的dp。由于涉及到匹配问题,只有一个串,考虑kmp。状态表示设\(f_{i,j}\)表示长度为\(i\)的字符串,与不吉利串的匹配长度为\(j\)的总方案数。状态转移......
  • 集装箱吊车门机起重机电气电器图纸
    集装箱吊车门机起重机电气电器图纸一套这是调试后的最终版图纸,含程序,元件清单,集装箱的,供学习参考用,这是电气图纸,没有机械的。plc是315-2dp,行车图纸有很多,串电阻的,各种变频,p......
  • 洛谷P3195 玩具装箱 题解报告
    题目地址题意:如题所述。分析:斜率优化dp模板题。题目没看清就下手,自以为题面所述中i>j;原始dp式子也没设计准确。中途在错误方向上头铁时,甚至没注意到横坐标是沿......
  • 如何用webgl(three.js)搭建一个3D库房,3D仓库3D码头,3D集装箱,车辆定位,叉车定位可视
    使用three.js(webgl)搭建智慧楼宇、3D园区、3D厂房、3D码头、3D海关、3D仓库、3D定位、三维室内定位、设备检测、数字孪生、物联网3D、物业3D监控、物业......
  • 基于YOLOv5实现集装箱检测跟踪
     首先展示下效果(cpu下),电脑配置如下,win10操作系统   最终的效果   下面进入实际操作1.安装anaconda与pycharm(不会可以百度下)2.运行anaconda 3......
  • Java中的拆箱与装箱
    概述Java提供了两个类型系统,基本类型与引用类型,使用基本类型在于效率,然而很多情况,会创建对象使用,因为对象可以做更多的功能,如果想要我们的基本类型像对象一样操作,就可以使......
  • 【JavaEE进阶系列 | 从小白到工程师】基本类型包装类的使用,装箱以及拆箱与parseInt方
    一、包装类概述Java中的数据类型分为基本类型和引用类型两大类,使用基本类型可以提升效率但是java是面向对象的语言,java的设计思想是一切皆对象,而基本数据类型不是对象,于是J......
  • BZOJ1009-[HNOI2008] GT考试
    [BZOJ1009][HNOI2008]GT考试Description    阿申准备报名参加GT考试,准考证号为N位数X1X2….Xn(0<=Xi<=9),他不希望准考证号上出现不吉利的数字。他的不吉利数学A1A2......
  • JAVA-自动装箱和拆箱
    packagecom.itheima;publicclassintegerDemo03{publicstaticvoidmain(String[]args){//装箱:把基本数据类型转化为对应的包装类类型;//In......
  • [HNOI2008]玩具装箱
    StatementLuoguSolution首先考虑最为暴力的做法,也就是我们直接设$f_i$表示将前$i$个玩具合并,那么有转移:$$f_i=\min_{j=1}^{i-1}{f_j+val(j+1,i)}$$这个时候很明......