poj 1390 Blocks

题意

一排带有颜色的砖块,每一个可以消除相同颜色的砖块,,每一次可以到块数k的平方分数。问怎么消能使分数最大。。

题解

此题在徐源盛《对一类动态规划问题的研究》以及刘汝佳的黑书《算法艺术与信息学竞赛》中都有提及。

首先我们要将相同颜色块进行合并。定义状态\(dp[i][j][k]\)表示第\(i\)到第\(j\)个颜色块后面接了\(k\)个颜色为\(color[j]\)的砖块。

不难得出转移方程为\(dp[i][j][k]=max \{ dp[i][j-1][0]+(len[j]+k)^2, dp[i][p][k+len[j]] + dp[p+1][j][0] \}\)

我们可以记录一下上一次\(color[j]\)出现的位置,就可以在\(O(n^3)\)内完成问题。

此题我写的是递推,不过记忆化似乎更快

递推

#include <cstdio>
#include <cstring> const int N = 205;
int dp[N][N][N], color[N], len[N], pre[N], pos[N];
inline void SelfMax(int &a, const int &b) { if (a < b) a = b; }
inline int p2(const int &a) { return a * a; }
int main() {
int n, pr, i, j, k, T, tot, a, Sizdp = sizeof dp, length, Case = 0;
scanf("%d", &T);
while (T--) {
n = 0; pr = -1; scanf("%d", &tot);
for (k = 1; k <= tot; ++k) {
scanf("%d", &a);
if (a != pr) color[++n] = pr = a, len[n] = 1;
else ++len[n];
} memset(dp, 0, Sizdp); memset(pos, 0, sizeof pos);
for (i = 1; i <= n; ++i) pre[i] = pos[color[i]], pos[color[i]] = i;
for (length = 1; length <= n; ++length)
for (i = 1;; ++i) {
if ((j = i + length - 1) > n) break;
for (k = 0; k <= tot; ++k) {
dp[i][j][k] = dp[i][j-1][0] + p2(len[j] + k);
for (a = pre[j]; a >= i; a = pre[a])
SelfMax(dp[i][j][k], dp[i][a][k+len[j]] + dp[a+1][j-1][0]);
}
}
printf("Case %d: %d\n", ++Case, dp[1][n][0]);
}
return 0;
}

记忆化

#include <cstdio>
#include <cstring> const int N = 205;
int dp[N][N][N], color[N], len[N], pre[N], pos[N], Sum[N]; inline void SelfMax(int &a, const int &b) { if (a < b) a = b; }
inline int p2(const int &a) { return a * a; } int f(int i, int j, int k) {
if (~dp[i][j][k]) return dp[i][j][k];
if (i > j) return 0;
int &ret = dp[i][j][k];
ret = f(i, j-1, 0) + p2(k + len[j]);
for (int p = pre[j]; p >= i; p = pre[p]) SelfMax(ret, f(i, p, k + len[j]) + f(p+1, j - 1, 0));
return ret;
}
int main() {
int n, pr, i, j, k, T, tot, a, Sizdp = sizeof dp, length, Case = 0;
scanf("%d", &T);
while (T--) {
n = 0; pr = -1; scanf("%d",&tot);
for (k = 1; k <= tot; ++k) {
scanf("%d", &a);
if (a ^ pr) color[++n] = pr = a, len[n] = 1;
else ++len[n];
} memset(dp, -1, Sizdp); memset(pos, 0, sizeof pos);
for (i = 1; i <= n; ++i) pre[i] = pos[color[i]], pos[color[i]] = i;
printf("Case %d: %d\n", ++Case, f(1, n, 0));
}
return 0;
}

poj 1390 Blocks的更多相关文章

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

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

  2. poj 1390 Blocks (经典区间dp 方块消除)

    Blocks Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 4250   Accepted: 1704 Descriptio ...

  3. POJ 1390 Blocks(区间DP)

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

  4. poj 1390 Blocks (记忆化搜索)

    Blocks Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 4318   Accepted: 1745 Descriptio ...

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

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

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

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

  7. 【POJ 1390】Blocks

    http://poj.org/problem?id=1390 黑书上的例题,感觉我这辈子是想不到这样的dp了QAQ \(f(i,j,k)\)表示将\(i\)到\(j\)合并,并且假设未来会有\(k\) ...

  8. Blocks POJ - 1390 多维dp

    题意:有一排box,各有不同的颜色.你可以通过点击某个box使得与其相邻的同色box全部消掉,然后你可以得到的分数为消去长度的平方,问怎样得到最高分? 题解:考虑用一维dp,/*dp[i]为1~i个b ...

  9. [POJ 3734] Blocks (矩阵高速幂、组合数学)

    Blocks Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 3997   Accepted: 1775 Descriptio ...

随机推荐

  1. python头部注释 vim添加头部注释

    1.先说说python和virtual python 一般环境下,python解释器会放在/usr/bin/ 下面,然后你执行python的时候就会运行了,但是如果没有在/usr/bin/下面的话,执 ...

  2. nodejs 中自定义事件

    经常看到 req.on('error', function(){...}); 这种代码. 在nodejs中,可以使用 EventEmitter来实现. 具体的关键词有如下几个: var reqEven ...

  3. [转载]Linux Bond的原理及其不足

    本文转自http://www.yunweipai.com/archives/1969.html 支持原创.尊重原创,分享知识! 在企业及电信Linux服务器环境上,网络配置都会使用Bonding技术做 ...

  4. W3School-CSS 外边距 (margin) 实例

    CSS 外边距 (margin) 实例 CSS 实例 CSS 背景实例 CSS 文本实例 CSS 字体(font)实例 CSS 边框(border)实例 CSS 外边距 (margin) 实例 CSS ...

  5. C++ 栈和堆的区别

    C++中的存储区分为全局数据区.代码区.堆.栈. 全局数据区存放静态数据.全局变量.常量. 代码区存放所有类成员函数和非成员函数的代码. 栈区存放用于函数的返回地址.形参.局部变量.返回类型. 堆区存 ...

  6. Linux 内核中的 Device Mapper 机制

    本文结合具体代码对 Linux 内核中的 device mapper 映射机制进行了介绍.Device mapper 是 Linux 2.6 内核中提供的一种从逻辑设备到物理设备的映射框架机制,在该机 ...

  7. Xamarin.Android VSTS 持续集成

    这些天做了一个基于 VSTS 的 Xamarin.Android的持续集成,这里分享下 Build Agent 环境需求 DotNetFramework msbuild visualstudio An ...

  8. 关于css的一些事情(1)

    什么情况下hidden不起作用? position设置成fixed,overflow的hidden不起作用. visibility和display 1.visibility: 规定了元素是否可见,即使 ...

  9. js获取键盘按下的键值event.keyCode,event.charCode,event.which的兼容性

    js获取键盘按下的键值有event.keyCode,event.charCode和event.which 其中: 谷歌浏览器对event.keyCode,event.charCode和event.wh ...

  10. RFID考试背诵

    简答题: 简述RFID标准多元化的原因: 由不同的技术因素.利益因素导致: 工作频率分布在低频至微波的多个频段中,频率不同,技术差异大. 作用距离的差异导致标准不同:因为应答器分为有源.无源两种工作方 ...