BZOJ 1010 玩具装箱toy(四边形不等式优化DP)(HNOI 2008)
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
输出最小费用
题目大意:略。
思路:由题意,令w(i, j) = (j - i + sum{c[i..j]} - L)^2
按照黑书(《算法艺术与信息学竞赛》)中的说法,要满足四边形不等式,只需要:
①j 不变时,f(i) = w(i, j + 1) - w(i, j)单调递减。
②i 不变时,f(j) = w(i + 1, j) - w(i, j)单调递减。
当且仅当①②都成立时,w符合四边形不等式(这题里面这个很好验证,就不写了)。
此时决策单调(虽然我不知道为什么……),解法可以参照《1D/1D动态规划优化初步》,我的解法就是参照这个写的。
另外,还有斜率优化的写法(虽然我不会),可以参照http://blog.sina.com.cn/s/blog_5f5353cc0100jx41.html
但是在我跑这样一组数据时(随机生成的):
50 5691358
8467214 9692279 8158876 7023812 4301767 4313397 2378849 778746 2288987 3052905 7228328 6855441 4280591 1058424 889808 530342 9432467 761829 3969985 3193649 8070892 711348 5821773 3062537 6891494 5695393 3803579 6418375 1578074 2363659 6477728 533247 6025318 8151154 2442635 1113076 506233 3594564 8277434 1584861 2276145 4442621 7105356 8729441 7283702 1250929 5133264 9233541 5267813 2889179
答案与我的程序跑出的结果136165306871056不一样。稍微目测了一下,上面斜率优化的代码越界了(我不知道怎么改了……)
w(i, j)的极限可高达(50000 - 1 + 50000 * 10^7 - 0)^2,超出了64位整数的范围(虽说似乎没有这样的大数据)。
本人的代码在修改后应该是不会存在越界的问题的(避免了两个较大数的乘法,可以参照代码里面的check函数)。
PS:答案一定不会大于50000 * (10^7 - 0)^2 = 5 * 10^18(就是每个玩具一个容器),比2^63-1稍微小那么一点。
代码(288MS):
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
typedef long long LL; const int MAXN = ; LL sum[MAXN], dp[MAXN];
int c[MAXN], n, L; LL sqrt_cost(int i, int j) {
return j - i + sum[j] - sum[i - ] - L;
} LL cost(int i, int j) {
LL res = sqrt_cost(i, j);
return res * res;
}
/*
bool check(int pos, int a, int b) {
return dp[a] + cost(a + 1, pos) >= dp[b] + cost(b + 1, pos);
}
*/
bool check(int pos, int a, int b) {
LL aa = dp[a], bb = sqrt_cost(a + , pos), cc = dp[b], dd = sqrt_cost(b + , pos);
return (cc - aa - ) / (bb - dd) + <= bb + dd;
} int binary_search(int st, int ed, int a, int b) {
int l = st, r = ed;
while(l < r) {
int mid = (l + r) >> ;
if(!check(mid, a, b)) l = mid + ;
else r = mid;
}
return l;
} struct Node {
int pos, best;
Node() {}
Node(int pos, int best): pos(pos), best(best) {}
} stk[MAXN];
int top; LL solve() {
int v = ;
stk[++top] = Node(, );
for(int i = ; i <= n; ++i) {
if(v < top && stk[v + ].pos <= i) ++v;
int p = stk[v].best;
dp[i] = dp[p] + cost(p + , i); while(v < top && check(stk[top].pos, stk[top].best, i))
--top;
int r = stk[top + ].pos ? stk[top + ].pos + : n + ;
int t = binary_search(max(stk[top].pos, i) + , r, stk[top].best, i);
if(t <= n) stk[++top] = Node(t, i);
}
return dp[n];
} int main() {
scanf("%d%d", &n, &L);
for(int i = ; i <= n; ++i) scanf("%d", &c[i]);
for(int i = ; i <= n; ++i) sum[i] = sum[i - ] + c[i];
cout<<solve()<<endl;
}
BZOJ 1010 玩具装箱toy(四边形不等式优化DP)(HNOI 2008)的更多相关文章
- BZOJ 1010 玩具装箱toy(斜率优化DP)
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1010 题目大意:P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他 ...
- P3195 [HNOI2008]玩具装箱TOY(斜率优化dp)
P3195 [HNOI2008]玩具装箱TOY 设前缀和为$s[i]$ 那么显然可以得出方程 $f[i]=f[j]+(s[i]-s[j]+i-j-L-1)^{2}$ 换下顺序 $f[i]=f[j]+( ...
- BZOJ 1010: [HNOI2008]玩具装箱toy(斜率优化dp)
http://www.lydsy.com/JudgeOnline/problem.php?id=1010 题意: 思路: 容易得到朴素的递归方程:$dp(i)=min(dp(i),dp(k)+(i-k ...
- BZOJ 1010: 玩具装箱toy (斜率优化dp)
Description P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1... ...
- 2018.09.05 bzoj1010: [HNOI2008]玩具装箱toy(斜率优化dp)
传送门 一道经典的斜率优化dp. 推式子ing... 令f[i]表示装前i个玩具的最优代价. 然后用老套路. 我们只考虑把第j+1" role="presentation" ...
- _bzoj1010 [HNOI2008]玩具装箱toy【斜率优化dp】
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1010 裸的斜率优化,第一次写队首维护的时候犯了个智障错误,队首维护就是维护队首,我怎么会那队 ...
- bzoj 1010 玩具装箱toy -斜率优化
P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1...N的N件玩具,第i件玩具 ...
- BZOJ 1010 [HNOI2008]玩具装箱toy:斜率优化dp
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1010 题意: 有n条线段,长度分别为C[i]. 你需要将所有的线段分成若干组,每组中线段的 ...
- BZOJ 1010: [HNOI2008]玩具装箱toy | 单调队列优化DP
原题: http://www.lydsy.com/JudgeOnline/problem.php?id=1010 题解: #include<cstdio> #include<algo ...
随机推荐
- opencv提取截获图像(总结摘来)
opencv提取截获图像(总结摘来) http://blog.csdn.net/wuxiaoyao12/article/details/7305865 版权声明:本文为博主原创文章,未经博主允许不得转 ...
- 应用github pages创建自己的个人博客
首先你需要注册自己的github账号 1.登录或者注册github,登录之后点击右上角的“+”号,选择“New repository”菜单,创建仓库,用于存储和博客相关的源文件. 2.跳转页面将填写域 ...
- Linq中常用的方法
这几天闲着也是闲着,就仔细的研究了一下Linq的语法,还有他的一些扩展方法的使用. 下面是一些常用的扩展方法. Aggregate 自定义的聚合计算 All 检测序列中所有元素是否都满足指定的条件 A ...
- MySQL-中文全文检索
一.概述 MySQL全文检索是利用查询关键字和查询列内容之间的相关度进行检索,可以利用全文索引来提高匹配的速度. 二.语法 1 2 MATCH (col1,col2,...) AGAINST (exp ...
- ubuntu下交叉编译windows c程序
简介 采用mingw32可以在linux下直接编译c程序输出为windows下的exe程序或dll链接库. 个人编译的纯c程序(不含winapi),主要是c99程序,通常采用gcc/cc编译调试后,再 ...
- FastReport的交叉表实际使用的一个例子
计算发行-->定义份数月表(打开)出现 PosFraisPaysInput选择时间段后,点击“打印”.这个设计表格,就是交叉表. 交叉表的特点是:数据库是一条一条并列的但是出来的结果却是:横向是 ...
- 安装Postman
原文地址:http://blog.csdn.net/ouyang111222/article/details/45743831 ** (一)安装篇 ** Postman是一款功能强大的网页调试与发送网 ...
- js获取div中的文本框数据
通过div得到div里的所有数据 大神的世界无需解释,当然不是说我,当我看到这些代码的时候我惊呆了! 这是一个工具方法js: js: /* * 获取指定对象下的所有input.textarea值 * ...
- JMeter学习-017-java.net.SocketException: Permission denied: connect 解决方案
前几天,有了新的接口性能测试需求,同事在添加 HTTP请求 后,运行时响应信息如下所示: java.net.SocketException: Permission denied: connect at ...
- 微信小程序:开发之前要知道的三件事
前言 微信之父张小龙在年初的那次演讲中曾表示:"我自己是很多年的程序员,我觉得我们应该为开发的团队做一些事情".几个月后,微信正式推出微信应用号(即微信小程序),在互联网中掀起了又 ...