POJ 1390 Blocks

砌块
时限:5000 MS   内存限制:65536K
提交材料共计: 6204   接受: 2563

描述

你们中的一些人可能玩过一个叫做“积木”的游戏。一行有n个块,每个盒子都有一个颜色。这是一个例子:金,银,铜,金。
相应的图片如下:
 
图1
如果一些相邻的盒子都是相同的颜色,并且它左边的盒子(如果它存在)和它的右边的盒子(如果它存在)都是其他颜色的,我们称它为“盒子段”。有四个盒子段。那就是:金,银,铜,金。片段中分别有1,4,3,1方框。

每次您可以单击一个框,然后包含该框的整个段消失。如果这段是由k个方框组成的,你会得到k*k点。例如,如果你点击一个银盒子,银段消失了,你得到4*4=16点。

现在让我们看看下面的图片:
 
图2

第一个是最优的。

在这个游戏的初始状态下,找出你能得到的最高分数。

输入

第一行包含测试数t(1<=t<=15)。每个案例包含两行。第一行包含整数n(1<=n<=200),即框数。第二行包含n个整数,表示每个框的颜色。整数在1~n的范围内。

输出量

对于每个测试用例,打印用例编号和最高可能的分数。

样本输入

2
9
1 2 2 2 2 3 3 3 1
1
1

样本输出

Case 1: 29
Case 2: 1

解题思路:

将连续的若干个方块作为一个“大块”(box_segment) 考虑,假设开始一共有 n个“大块”,编号0到n-1 第i个大块的颜色是 color[i],包含的方块数目,即长度,是len[i]

用click_box(i,j)表示从大块i到大块j这一段消除后所能 得到的最高分,则整个问题就是: click_box(0,n-1)。

要求click_box(i,j)时,考虑最右边的大块j,对它有两种处理方式,要取其优者:

1) 直接消除它,此时能得到最高分就是: click_box(i,j-1) + len[j]*len[j]

2) 期待以后它能和左边的某个同色大块合并,考虑和左边的某个同色大块合并:

左边的同色大块可能有很多个,到底和哪个合并最 好,不知道,只能枚举。假设大块j和左边的大块 k(i<=k<j-1) 合并,此时能得到的最高分是多少呢?

是不是: click_box(i,k-1) + click_box(k+1,j-1) + (len[k]+len[j])

不对! 因为将大块k和大块j合并后,形成的新大块会在最右边。但直接将其消去,未必是最好的,也许它还应该和左边的同色大块合并,才更好

那么上面的dp不可用,需要改变问题的形式

__________________________________________________________________

click_box(i,j,ex_len) 表示: 大块 j 的右边已经有一个长度为ex_len的大块(该大块可能是在合并过程中形成的),且 j 的颜色和ex_len相同,在此情况下所能得到的最高分 。

于是整个问题就是求:click_box(0,n-1,0)

求click_box(i,j,ex_len)时,有两种处理方法取最优者,假设j和ex_len合并后的大块称作 Q

1) 将Q直接消除,这种做法能得到的最高分就是:  click_box(i,j-1,0) + (len[j]+ex_len)2

2) 期待Q以后能和左边的某个同色大块合并。需要枚举可能和Q 合并的大块。假设让大块k和Q合并,则此时能得到的最大分数是:

  click_box(i,k,len[j]+ex_len) + click_box(k+1,j-1,0)

click_box(i,j,ex_len) 递归的终止条件: i == j

代码:

#include<iostream>
#include<cstring>
using namespace std;
#define N 200 + 5
int dp[N][N][N];
struct segMent {
int len;
int color;
};
segMent segNum[N];
int clickBox(int i, int j, int len) {
if(dp[i][j][len] != -) return dp[i][j][len];
int result = (segNum[j].len + len)*(segNum[j].len + len);
if(i == j) return result;
result += clickBox(i, j-, );
for(int k = i; k < j; k++) {
if(segNum[k].color != segNum[j].color) continue;
int r = clickBox(k+, j-, ) + clickBox(i, k, segNum[j].len + len);
result = max(result, r);
}
dp[i][j][len] = result;
return result;
}
int main() {
int T;
cin >> T;
for(int t = ; t <= T; t++) {
int n;
cin >> n;
int last = -;
int count = -;
memset(dp, -, sizeof(dp));
for(int i = ; i < n; i++) {
int v;
cin >> v;
if(v != last) {
count++;
segNum[count].len = ;
segNum[count].color = v;
last = v;
} else segNum[count].len++;
}
cout << "Case " << t << ": " << clickBox(, count, ) << endl;
}
return ;
}

POJ 1390 Blocks(记忆化搜索+dp)的更多相关文章

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

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

  2. POJ 1088 滑雪(记忆化搜索+dp)

    POJ 1088 滑雪 Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 107319   Accepted: 40893 De ...

  3. 记忆化搜索(DP+DFS) URAL 1183 Brackets Sequence

    题目传送门 /* 记忆化搜索(DP+DFS):dp[i][j] 表示第i到第j个字符,最少要加多少个括号 dp[x][x] = 1 一定要加一个括号:dp[x][y] = 0, x > y; 当 ...

  4. HDU 1078 FatMouse and Cheese 记忆化搜索DP

    直接爆搜肯定超时,除非你加了某种凡人不能想出来的剪枝...555 因为老鼠的路径上的点满足是递增的,所以满足一定的拓补关系,可以利用动态规划求解 但是复杂的拓补关系无法简单的用循环实现,所以直接采取记 ...

  5. 记忆化搜索 dp学习~2

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1331 Function Run Fun Time Limit: 2000/1000 MS (Java/ ...

  6. 【10.31校内测试】【组合数学】【记忆化搜索/DP】【多起点多终点二进制拆位Spfa】

    Solution 注意取模!!! Code #include<bits/stdc++.h> #define mod 1000000007 #define LL long long usin ...

  7. hdu1331&&hdu1579记忆化搜索(DP+DFS)

    这两题是一模一样的``` 题意:给了一系列递推关系,但是由于这些递推很复杂,所以递推起来要花费很长的时间,所以我要编程序在有限的时间内输出答案. w(a, b, c): 如果a,b,c中有一个值小于等 ...

  8. HDU - 6415 多校9 Rikka with Nash Equilibrium(纳什均衡+记忆化搜索/dp)

    Rikka with Nash Equilibrium Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 524288/524288 K ...

  9. hdu 4960 记忆化搜索 DP

    Another OCD Patient Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Ot ...

随机推荐

  1. Java代码优化,都有哪些常用方法?

    Java代码优化是Java编程开发很重要的一个步骤,Java代码优化要注重细节优化,一个两个的细节的优化,产生的效果不大,但是如果处处都能注意代码优化,对代码减少体积.提高代码运行效率是有巨大帮助的, ...

  2. vue中eslintrc.js配置最详细介绍

    本文是对vue项目中自带文件eslintrc.js的内容解析, 介绍了各个eslint配置项的作用,以及为什么这样设置. 比较详细,看完能对eslint有较为全面的了解,基本解除对该文件的疑惑. /* ...

  3. java与js交互,相互调用传参

    随着前端技术的发展与H5的广泛使用,移动端采用native+h5的方式越来越多了,对于Android来说就涉及到java与js的交互,相互调用传参等.下面就来看一下java与js交互的简单demo. ...

  4. 基于虹软sdk,java实现人脸识别(demo)

    ## 开发环境准备:###开发使用到的软件和工具:* Jdk8.mysql5.7.libarcsoft_face.dll(so).libarcsoft_face_engine.dll(so).liba ...

  5. English trip V1 - B 5.Is It Cold Outside? 外面很冷? Teacher:Corrine Key: weather

    In this lesson you will learn to talk about the weather. 本节课将学习到关于天气 课上内容(Lesson) 词汇(Key Word ) # 关于 ...

  6. 分享WCF文件传输---WCFFileTransfer

    前几天分享了分享了WCF聊天程序--WCFChat , 本文和大家一起分享利用WCF实现文件的传输.程序运行效果:接收文件端:发送文件端:连接WCF服务,选择要传输的文件文件传输成功:我们会在保存文件 ...

  7. LeetCode--042--接雨水(java版)

    给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水. 上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 ...

  8. 4.1.3 Euclid's Game (POJ 2348)

    Problem description: 以辗转相除法为基础,给定两个整数a和b,Stan和Ollie轮流从较大的数字中减去较小数字的倍数(整倍数),并且相减后的结果不能为零.Stan先手,在自己的回 ...

  9. 《剑指offer》总结一

    目录 1.二维数组中的查找(223ms) 2.替换空格(24ms) 3.从尾到头打印链表(22ms) 4.重建二叉树(37ms) 5.用两个栈实现队列 1.二维数组中的查找(223ms) 题目描述: ...

  10. raw_input 和input 区别

    raw_input() 直接读取控制台的输入(任何类型的输入它都可以接收).而对于 input() ,它希望能够读取一个合法的 python 表达式,即你输入字符串的时候必须使用引号将它括起来,否则它 ...