【动态规划】玩具装箱

原创 2012年03月23日 11:11:21

Description
P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京。他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中。P教授有编号为1...N的N件玩具,第i件玩具经过压缩后变成一维长度为Ci.为了方便整理,P教授要求在一个一维容器中的玩具编号是连续的。同时如果一个一维容器中有多个玩具,那么两件玩具之间要加入一个单位长度的填充物,形式地说如果将第i件玩具到第j个玩具放到一个容器中,那么容器的长度将为 x=j-i+Sigma(Ck) i<=K<=j 制作容器的费用与容器的长度有关,根据教授研究,如果容器长度为x,其制作费用为(X-L)^2.其中L是一个常量。P教授不关心容器的数目,他可以制作出任意长度的容器,甚至超过L。但他希望费用最小.
Input
第一行输入两个整数N,L.接下来N行输入Ci.1<=N<=50000,1<=L,Ci<=10^7
Output
输出最小费用
Sample Input
5 4
3
4
2
1
4
Sample Output
1
设s数组为前缀和,令g[i] = i + s[i]。

朴素的方程:f[i] = max{f[j] + sqr(g[i] - g[j] - l - len)}。
设j为当前最优决策,k为j右边一点,通过化简,可以得到斜率不等式:
 f[j] - f[k]
——————- + g[j] + g[k] + 2len + 2 >= 2g[i]
 g[j] - g[k]
令不等式的左边为H(j, k)。

只需要用双端队列维护一个H值不断上升(下凸函数)的决策序列即可。
Accode:

#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <algorithm>

const char fi[] = "toy.in";
const char fo[] = "toy.out";
const int maxN = 50010;
const int MAX = 0x3f3f3f3f;
const int MIN = ~MAX;

typedef long long int64;
int64 F[maxN], g[maxN], s[maxN], len;
int q[maxN], n, f, r;

void init_file()
{
    freopen(fi, "r", stdin);
    freopen(fo, "w", stdout);
    return;
}

inline int getint()
{
    int res = 0; char tmp;
    while (!(isdigit(tmp = getchar())));
    do res = (res << 3) + (res << 1) + tmp - '0';
    while ((isdigit(tmp = getchar())));
    return res;
}

void readdata()
{
    n = getint(); len = getint();
    for (int i = 1; i < n + 1; ++i)
    {
        (s[i] = getint()) += s[i - 1];
        g[i] = i + s[i];
    }
    return;
}

#define sqr(x) ((x) * (x))

#define check(j, k, i) \
(F[j] - F[k] + (g[j] + g[k] + \
(len << 1) + 2) * (g[j] - g[k]) \
<= (g[i] * (g[j] - g[k]) << 1))

#define cmp(j, k, i) \
((F[j] - F[k] + (g[j] + g[k] + \
(len << 1) + 2) * (g[j] - g[k])) \
* (g[k] - g[i]) \
<= (F[k] - F[i] + (g[k] + g[i] + \
(len << 1) + 2) * (g[k] - g[i])) \
* (g[j] - g[k]))

void work()
{
    f = 0, r = 1; //
    for (int i = 1; i < n + 1; ++i)
    {
        while (f < r - 1 && !check(q[f], q[f + 1], i)) ++f;
        F[i] = F[q[f]] + sqr(g[i] - g[q[f]] - 1 - len);
        while (f < r - 1 && !cmp(q[r - 2], q[r - 1], i)) --r;
        q[r++] = i;
    }
    printf("%I64d\n", F[n]);
    return;
}

int main()
{
    init_file();
    readdata();
    work();
    return 0;
}

#undef sqr
#undef check
#undef cmp

【HNOI2002】bzoj1010 玩具装箱

斜率优化dp
  • sdfzyhx
  • sdfzyhx
  • 2016年07月24日 14:27
  • 183

[BZOJ1010][HNOI2008]玩具装箱toy 斜率优化第一题

很明显我们得到朴素的转移方程dp[i]=min{dp[j]+(i−j−1+sum[i]−sum[j]−L)2,dp[i]}  (0≤j...
  • slongle_amazing
  • slongle_amazing
  • 2015年12月16日 17:13
  • 1682

动态规划装箱问题

思路: 动态规划: 假设可选物品集合为S, Sk为前k个物品组成的物品子集, 第k个物品的体积是wk,价值是vk 1. 表征子问题:用B[k,w] 表示在子集Sk中,所剩空间为w时,能够装下的物...
  • qq695181966
  • qq695181966
  • 2014年04月30日 20:31
  • 516

bzoj1010[HNOI2008] 玩具装箱toy(带斜率优化学习笔记)

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1010 题目大意: 有n个数,分成连续的若干段,每段(假设从第j个到第i个组成一段)的分数为...
  • u010336344
  • u010336344
  • 2016年09月22日 13:58
  • 999

[BZOJ]1010 玩具装箱

[BZOJ]1010题意:P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京。他使用自己的压缩器进行压 缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中。P教授有编号为1...
  • sssSSSay
  • sssSSSay
  • 2017年04月17日 21:34
  • 243

装箱问题的动态规划算法和渐进ptas

装箱问题的动态规划算法和渐进ptasinstance:给定n个物体,大小分别为s1,s2,…,sns_1,s_2,\dots,s_n,将其放进大小为m的箱子里问,需要的最少的箱子的数目是多少。可以将这...
  • Hlveying
  • Hlveying
  • 2017年12月29日 14:58
  • 31

SSL 1640——叠放箱子问题

Description  某港口有一批集装箱,将其编号,分别为1至N。每一个箱子的外型尺寸都是一样的,现在要将其中某些集装箱叠放起来,集装箱叠放的规则如下:   1)每个集装箱上最多只能直接叠放一...
  • SSL_ZZY
  • SSL_ZZY
  • 2017年03月11日 16:17
  • 173

【bzoj1010】【HNOI2008】【玩具装箱】【toy】【动态规划】【斜率优化】

题目大意: 有编号为1..N的N件玩具,第i件玩具长度是Ci。可以将任意编号连续的玩具变成一堆,再装到容器中。如果一堆中有多个玩具,那么每两件玩具之间要加入1个单位长度的填充物。 ...
  • chunkitlau
  • chunkitlau
  • 2015年08月13日 16:45
  • 241

动态规划——装箱问题

有一个箱子容量为V(正整数,0<=V<=20000),同时有n个物品(0<n<=30),每个物品有一个体积(正整数)。 要求n个物品中,任取若干个装入箱内,使箱子的剩余空间为最小。 输入描述 In...
  • qq_18860653
  • qq_18860653
  • 2016年11月21日 16:46
  • 2246

【动态规划18】bzoj1010 [HNOI2008]玩具装箱toy(斜率优化)

斜率优化 导公式的时候稍微要动一下脑子
  • Flanoc
  • Flanoc
  • 2017年06月19日 20:20
  • 187
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:【动态规划】玩具装箱
举报原因:
原因补充:

(最多只允许输入30个字)