$ POJ1390~Blocks: $ (很难想的区间DP)



$ solution: $

很好的一道题目。看起来似乎很简单,当时一直认为可以用二维区间DP来完成,转移 $ n^3 $ 。 后来发现如果用二维表示当前状态,转移可以说无路可走。因为可能存在原本不相邻的多个区间最后是一起消除的。所以我们需要保留下来某一段重复的区间做为我们的一个新的维度。

或者说,(存在原本不相邻的多个区间最后是一起消除的)这个过程也是可以从后向前消除,只是保留最后的一段相同区间,先消掉它前面的区间,比如12131这个数列,我们可以先将3消掉,使两个1到一块来:1211,然后再消掉2,使剩下的一个1也合拢来:111。于是我们考虑在原有维度上加一维,它保留最后一段区间的信息,但是我们就需要同时记录颜色和长度,这不是一个维度能干的事,所以我们换一种方式:

注:出于贪心,也为了方便做题,我们先将数列里连续相同的一段合并,用 $ b[i] $ 表示其长度

设 $ f[i][j][k] $ 表示区间 $ [i,j] $ 并且后面有连续k个格子的颜色和 $ j $ 号格子相同。这时,转移就会相对容易些:

  1. 将后面的连续k个格子的颜色和 $ j $ 号格子合并: $ f[i][j][k]=f[i][j-1][0]+(b[j]+k)^2 $
  2. 枚举 $ [i,j) $ 内的一个格子 $ x $ ,这个格子需与 $ j $ 号格子颜色一致,然后消掉这个格子与 $ j $ 号格子之间的格子: $ f[i][j][k]=f[i][x][b[j]+k+1]+f[x+1][j-1][0] $

然后我们发现这个题目转移只涉及了 $ f $ 数组,所以我们可以用记忆化搜索(递归)处理。



$ code: $

#include<iostream>
#include<cstdio>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set> #define ll long long
#define db double
#define rg register int using namespace std; int t,tt,n,m;
int a[205],b[205];
int f[205][205][205];
int d[205][205][205]; inline int qr(){
register char ch; register bool sign=0; rg res=0;
while(!isdigit(ch=getchar()))if(ch=='-')sign=1;
while(isdigit(ch))res=res*10+(ch^48),ch=getchar();
if(sign)return -res; else return res;
} inline int dfs(int x,int y,int z){
if(y<x)return 0; if(x==y)return (b[x]+z)*(b[x]+z);
if(d[x][y][z]==tt)return f[x][y][z];
f[x][y][z]=dfs(x,y-1,0)+(z+b[y])*(z+b[y]);
for(rg i=x;i<y;++i){
if(a[i]!=a[y])continue;
f[x][y][z]=max(f[x][y][z],dfs(x,i,b[y]+z)+dfs(i+1,y-1,0));
}return d[x][y][z]=tt,f[x][y][z];
} int main(){
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
t=qr();
while(++tt<=t){
n=qr(); m=0;
for(rg i=1;i<=n;++i,++b[m])
if((a[m+1]=qr())!=a[m])++m,b[m]=0;
printf("Case %d: %d\n",tt,dfs(1,m,0));
}
return 0;
}

POJ-1390-Blocks (复杂区间DP)的更多相关文章

  1. POJ 1390 Blocks(记忆化搜索+dp)

    POJ 1390 Blocks 砌块 时限:5000 MS   内存限制:65536K 提交材料共计: 6204   接受: 2563 描述 你们中的一些人可能玩过一个叫做“积木”的游戏.一行有n个块 ...

  2. poj 1390 Blocks

    poj 1390 Blocks 题意 一排带有颜色的砖块,每一个可以消除相同颜色的砖块,,每一次可以到块数k的平方分数.问怎么消能使分数最大.. 题解 此题在徐源盛<对一类动态规划问题的研究&g ...

  3. Blocks题解(区间dp)

    Blocks题解 区间dp 阅读体验...https://zybuluo.com/Junlier/note/1289712 很好的一道区间dp的题目(别问我怎么想到的) dp状态 其实这个题最难的地方 ...

  4. POJ 1390 Blocks(区间DP)

    Blocks [题目链接]Blocks [题目类型]区间DP &题意: 给定n个不同颜色的盒子,连续的相同颜色的k个盒子可以拿走,权值为k*k,求把所有盒子拿完的最大权值 &题解: 这 ...

  5. POJ 1390 Blocks (区间DP) 题解

    题意 t组数据,每组数据有n个方块,给出它们的颜色,每次消去的得分为相同颜色块个数的平方(要求连续),求最大得分. 首先看到这题我们发现我们要把大块尽可能放在一起才会有最大收益,我们要将相同颜色块合在 ...

  6. POJ 1390 Blocks(DP + 思维)题解

    题意:有一排颜色的球,每次选择一个球消去,那么这个球所在的同颜色的整段都消去(和消消乐同理),若消去k个,那么得分k*k,问你消完所有球最大得分 思路:显然这里我们直接用二位数组设区间DP行不通,我们 ...

  7. POJ - 3280Cheapest Palindrome-经典区间DP

    POJ - 3280 Cheapest Palindrome Time Limit: 2000MS   Memory Limit: 65536KB   64bit IO Format: %I64d & ...

  8. poj 2955 括号匹配 区间dp

    Brackets Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6033   Accepted: 3220 Descript ...

  9. 【Uva10559】Blocks(区间DP)

    Description 题意:有一排数量为N的方块,每次可以把连续的相同颜色的区间消除,得到分数为区间长度的平方,然后左右两边连在一起,问最大分数为多少. \(1\leq N\leq200\) Sol ...

  10. POJ 3280 Cheapest Palindrome (区间DP) 经典

    <题目链接> 题目大意: 一个由小写字母组成的字符串,给出字符的种类,以及字符串的长度,再给出添加每个字符和删除每个字符的代价,问你要使这个字符串变成回文串的最小代价. 解题分析: 一道区 ...

随机推荐

  1. Mybatis,模糊查询语句,以及传参数的正确写法

    不多说直接上代码! 接口: public interface CommodityMapper { int deleteByPrimaryKey(Integer productId); int inse ...

  2. C++ Primer 第四版阅读笔记

    阅读笔记 初始化 变量定义指定了变量的类型和标识符,也可以为对象提供初始值.定义时指定了初始值的对象被称为是 已初始化的.C++ 支持两种初始化变量的形式:复制初始化和 直接初始化.复制初始化语法用等 ...

  3. Prototype js library

    Prototype An object-oriented JavaScript framework Prototype is a JavaScript framework that aims to e ...

  4. fedora禁用(开机启动)服务和进程管理

    首先要查看有哪些(开机启动)服务 chkconfig --list 或者: systemctl list-units 然后, 根据需要进行禁用服务的开机启动: chkconfig service_na ...

  5. mysql 无法存储表情字符 java.sql.SQLException: Incorrect string value: '\xF0\x9F\x90\xBE",...' for column 'XXXX' at row 1

    1.变更字段类型 ALTER TABLE api_log MODIFY COLUMN remark longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_uni ...

  6. 设计模式-Runoob:工厂模式

    ylbtech-设计模式-Runoob:工厂模式 1.返回顶部 1. 工厂模式 工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一.这种类型的设计模式属于创建型模式,它提供 ...

  7. 【转】一个 Vim 重度用户总结的 vim 超全指南

    [转]一个 Vim 重度用户总结的 vim 超全指南 我本人是 Vim 的重度使用者,就因为喜欢上这种双手不离键盘就可以操控一切的feel,Vim 可以让我对文本的操作更加精准.高效. 对于未使用过 ...

  8. 查看centos的版本信息

    1.查看centos的版本信息 cat /etc/centos-release

  9. VMware 虚拟化编程(9) — VMware 虚拟机的快照

    目录 目录 前文列表 VMware 虚拟机的快照 快照的执行过程 删除快照 快照类型 Quiseced Snapshot 前文列表 VMware 虚拟化编程(1) - VMDK/VDDK/VixDis ...

  10. 《计算机程式设计》Week4 课堂笔记

    本笔记记录自 Coursera课程 <计算机程式设计> 台湾大学 刘邦锋老师 Week4 Functions 4-1 System Function 函数主要分为两大类系统定义函数与使用者 ...