【题解】【THUSC 2016】成绩单 LOJ 2292 区间dp
Prelude
快THUWC了,所以补一下以前的题。
真的是一道神题啊,网上的题解没几篇,而且还都看不懂,我做了一天才做出来。
传送到LOJ:(>人<;)
Solution
直接切入正题。
我们考虑区间dp,第一件事是离散化。
然后用\(g(i,j)\)表示消除完闭区间\([i,j]\)的最小费用。
然后呢?怎么转移?exm???
这时候会有一个非常自然的想法。
计算\(g(i,j)\)的时候,我们枚举两个数\(l,r\),然后保留下值在闭区间\([l,r]\)之内的所有数,先消除掉其他的数字,就只剩\([l,r]\)之内的数字了,再一次性消除掉她们。
时间复杂度\(O(n^5)\),但是显然是错的。
错在哪里呢?大概是错在下面这种情况,我懒得构造具体的反例了。
对于一组数字\(abcabca\),我们可以先消除掉中间的\(a\),再消除掉\(bcbc\),最后再消除掉\(aa\),在我们的dp里面似乎并没有考虑到这种情况。
因为\(aa\)是最后消除掉的,因此如果我们选择保留\(a\)的话,会保留下来所有的\(a\)。
我们太仁慈了,保留下来了\([l,r]\)之间的所有的数字,其实不一定要保留所有数字。
怎么办呢?
脑洞大开!
我们用\(f(i, j, l, r)\)表示,消除完在闭区间\([i,j]\)之内的,除了值在\([l,r]\)之间的所有数字。
注意,在\([l,r]\)之间的数字,可以消除,也可以不消除。
然后显然有这个东西:
$\Large g(i, j) = \min f(i, j, l, r)$
实际上就是枚举$l,r$嘛。
然后我们考虑$f(i, j, l, r)$如何转移。
当闭区间$[i,j]$内元素全部在$[l,r]$之间的时候,显然$f(i, j, l, r)=0$。
当闭区间$[i,j]$内元素全部不在$[l,r]$之间的时候,显然$f(i, j, l, r)=g(i, j)$。
$f(i, j, l, r)=g(i, j)$似乎构成了循环依赖?
那么,我们枚举$l,r$的时候,必须保证区间$[i,j]$内存在至少一个数字在$[l,r]$内,这样就不会有循环依赖了。
解决了$f(i, j, l, r)$的边界问题,接下来看如何转移。
像普通的区间dp一样,我们枚举区间的分裂点$k$,然后把区间$[i,j]$分裂成$[i,k]$和$[k+1,j]$两部分,递归做下去。
有式子:
$\Large f(i, j, l, r) = \min f(i, k, l, r) + f(k+1, j, l, r)$
感受一下,感觉似乎是能处理各种情况的?
但是实际上和刚刚的做法没有任何区别。
因为对于状态$f(i, j, l, r)$,我们仍然保留了$[l,r]$之间的所有数字,仍然是那么的仁慈。
我们需要加一种暴力斩掉所有数字的情况。
有式子:
$\Large f(i, j, l, r) = \min g(i, k) + f(k+1, j, l, r)$
仔细感受一下,这两个$f(i, j, l, r)$的转移式结合起来之后,就可以处理掉所有情况了!
时间复杂度仍然是$O(n^5)$。
实现采用记忆化搜索,效果棒棒哒~
真是一道神题啊。。。
Code
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <iostream>
using namespace std;
const int N = 52;
const int W = 1010;
const int INF = 0x3f3f3f3f;
int _w;
int bmin( int &a, int b ) {
return a = b < a ? b : a;
}
int n, a, b, w[N];
int vis[W], num[N], m;
int f[N][N][N][N], g[N][N];
int F( int, int, int, int );
int G( int, int );
void discrete() {
for( int i = 1; i <= n; ++i )
vis[w[i]] = 1;
m = 1;
for( int i = 1; i < W; ++i )
if( vis[i] )
vis[i] = m, num[m++] = i;
--m;
for( int i = 1; i <= n; ++i )
w[i] = vis[w[i]];
}
bool contain( int i, int j, int l, int r ) {
for( int p = i; p <= j; ++p )
if( w[p] >= l && w[p] <= r )
return true;
return false;
}
bool all( int i, int j, int l, int r ) {
for( int p = i; p <= j; ++p )
if( w[p] < l || w[p] > r )
return false;
return true;
}
int F( int i, int j, int l, int r ) {
int &now = f[i][j][l][r];
if( now != -1 ) return now;
if( all(i, j, l, r) ) return now = 0;
if( !contain(i, j, l, r) ) return now = G(i, j);
now = INF;
for( int k = i; k < j; ++k ) {
bmin( now, F(i, k, l, r) + F(k+1, j, l, r) );
bmin( now, G(i, k) + F(k+1, j, l, r) );
}
// printf( "f[%d][%d][%d][%d] = %d\n", i, j, l, r, now );
return now;
}
int G( int i, int j ) {
int &now = g[i][j];
if( now != -1 ) return now;
now = INF;
for( int l = 1; l <= m; ++l )
for( int r = l; r <= m; ++r )
if( contain(i, j, l, r) ) {
int u = num[l], v = num[r];
bmin( now, F(i, j, l, r) + (v-u)*(v-u)*b + a );
}
// printf( "g[%d][%d] = %d\n", i, j, now );
return now;
}
int main() {
cin >> n >> a >> b;
for( int i = 1; i <= n; ++i )
cin >> w[i];
discrete();
memset(f, -1, sizeof f);
memset(g, -1, sizeof g);
printf( "%d\n", G(1, n) );
return 0;
}
【题解】【THUSC 2016】成绩单 LOJ 2292 区间dp的更多相关文章
- loj 1031(区间dp+记忆化搜索)
题目链接:http://lightoj.com/volume_showproblem.php?problem=1031 思路:dp[i][j]表示从区间i-j中能取得的最大值,然后就是枚举分割点了. ...
- BZOJ 1996: [Hnoi2010]chorus 合唱队(区间dp)
题目: https://www.lydsy.com/JudgeOnline/problem.php?id=1996 题解: 这题刚拿到手的时候一脸懵逼qwq,经过思考与分析(看题解),发现是一道区间d ...
- 「USACO16OPEN」「LuoguP3146」248(区间dp
题目描述 Bessie likes downloading games to play on her cell phone, even though she doesfind the small to ...
- SPOJ MIXTURES 区间dp
Harry Potter has n mixtures in front of him, arranged in a row. Each mixture has one of 100 differen ...
- UVA1630 Folding 区间DP
Folding Description Bill is trying to compactly represent sequences of capital alphabetic characte ...
- LOJ 2292 「THUSC 2016」成绩单——区间DP
题目:https://loj.ac/problem/2292 直接 DP 很难做,主要是有那种 “一个区间内部有很多个别的区间” 的情况. 自己想了一番枚举 max-min 的最大限制,然后在该基础上 ...
- loj 2292「THUSC 2016」成绩单
loj 看着就很区间dp,所以考虑求\(f_{i,j}\)表示区间\([i,j]\)的答案.注意到贡献答案的方式是每次选一个连续段,拿走后剩下的段拼起来继续段,所以转移就考虑从最后一次选的方法转移过来 ...
- 2016 ACM/ICPC Asia Regional Shenyang Online 1009/HDU 5900 区间dp
QSC and Master Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) ...
- 【bzoj4897】[Thu Summer Camp2016]成绩单 区间dp
题目描述 给你一个数列,每次你可以选择连续的一段,付出 $a+b\times 极差^2$ 的代价将其删去,剩余部分拼到一起成为新的数列继续进行此操作.求将原序列全部删去需要的最小总代价是多少. 输入 ...
随机推荐
- webpack开发和生产两个环境的配置详解
一开始在接触webpack 的时候,简直痛不欲生,现在回头看,做个注释,当然参考了很多文章.这是一个关于vue 开发的webpack 架构会列举出来webpack 系列教程Webpack——令人困惑的 ...
- Vue 入门之数据绑定
什么是双向绑定? Vue 框架很核心的功能就是双向的数据绑定. 双向是指:HTML 标签数据 绑定到 Vue 对象,另外反方向数据也是绑定的.通俗点说就是,Vue 对象的改变会直接影响到 HTML 的 ...
- Struts2框架学习
Struts功能详解——ActionMapping对象 ActionMapping描述了struts中用户请求路径和Action的映射关系,在struts中每个ActionMapping都是通过pat ...
- 优化Hibernate所鼓励的7大措施:
优化Hibernate所鼓励的7大措施: 1.尽量使用many-to-one,避免使用单项one-to-many 2.灵活使用单向one-to-many 3.不用一对一,使用多对一代替一对一 4.配置 ...
- Myeclipse(2014)项目的注释乱码
(之前都是在项目右键 propertits----resource---text file encoding 里面改成UTF-8的 下面是以后都直接换) window->preference-& ...
- mvc 路由配置-学习2
public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { r ...
- 今年暑假要AC
今年暑假要AC 在这个大学的第一个的暑假,谁不想回去high呢~ 但是,这是不行的,还没有AC,你能回去吗?高三那年的暑假怎么玩的,现在补回来吧...有规模有计划有氛围的学习就是:优点多效率好激情足~ ...
- Alpha冲刺阶段博客汇总
第一篇(冲刺前安排):http://www.cnblogs.com/Aragaki-Yui/p/8893752.html 第二篇(冲刺第一天):http://www.cnblogs.com/Araga ...
- 0603团队变化+sprint第二个冲刺
开始一个新的冲刺: 起止:2016.6.1~2016.6.14 按照以下过程进行 ProductBacklog:继续向下细化 Sprint 计划会议:确定此次冲刺要完成的目标 Sprint Backl ...
- 『编程题全队』Alpha 阶段冲刺博客Day2
1.每日站立式会议 1.会议照片 2.昨天已完成的工作统计 孙志威: 确定了本阶段的团队目标 确定了个人所分配的任务(主要为客户端GUI模块) 孙慧君: 确定了自己的任务,并着手开始环境 ...