UVa 10559 Blocks - 动态规划

题目传送门

  传送门

题目大意

  有$n$个方块排成一排,每次可以选择一段连续相同的颜色的方块消去并将两端拼接起来,设消去的长度为$x$,那么可以得到$x^2$的分数。问消去所有方块后的最高得分。

  标算的状态设计感觉比较神仙。

  设$f_{l, r, k}$表示考虑到第$l$个方块到第$r$个方块,在第$r$个方块后面有$k$个和第$r$个方块的颜色一样的方块,将这些方块都消去能够得到的最大的分数。

  首先不难发现每次消除一定消除的是当前一个极大颜色相同的连续段。

  转移的时候考虑$r$所在原序列的一个极大颜色相同的连续段。显然有两种决策:

  • 把它和后面的$k$的方块一起消掉。
  • 把它作为$[l, r]$某个子区间$[l, r‘]$的右边和$r‘$颜色相同的方块,然后将$r‘$的后一个方块到$r$所在原序列的一个极大颜色相同的连续段的第一个方块的前一个方块之间的方块(包含端点)先消去(这样使得$r‘$和$r$所在的那个连续段连接在一起)。

  时间复杂度$O(n^4)$。([一脸懵逼.gif])

Code

 1 /**
 2  * UVa
 3  * Problem#10559
 4  * Accepted
 5  * Time: 670ms
 6  */
 7 #include <iostream>
 8 #include <cstdlib>
 9 #include <cstring>
10 #include <cstdio>
11 using namespace std;
12 typedef bool boolean;
13
14 const int N = 205;
15
16 int n;
17 int a[N], f[N][N][N];
18
19 inline void init() {
20     scanf("%d", &n);
21     for (int i = 1; i <= n; i++)
22         scanf("%d", a + i);
23 }
24
25 int dp(int l, int r, int append) {
26     if (l > r)
27         return 0;
28     int& rt = f[l][r][append];
29     if (~rt)
30         return rt;
31     int cont = 1, k = r;
32     while (k > l && a[k - 1] == a[r])
33         k--, cont++;
34     rt = dp(l, k - 1, 0) + (cont + append) * (cont + append);
35     for (int i = l; i < k; i++)
36         if ((a[i + 1] != a[i]) && a[i] == a[k])
37             rt = max(rt, dp(l, i, append + cont) + dp(i + 1, k - 1, 0));
38     return rt;
39 }
40
41 inline void solve() {
42     static int Kase = 0;
43     memset(f, -1, sizeof(f));
44     printf("Case %d: %d\n", ++Kase, dp(1, n, 0));
45 }
46
47 int T;
48 int main() {
49     scanf("%d", &T);
50     while (T--) {
51         init();
52         solve();
53     }
54     return 0;
55 }

原文地址:https://www.cnblogs.com/yyf0309/p/9918212.html

时间: 2024-10-13 17:16:11

UVa 10559 Blocks - 动态规划的相关文章

UVA - 10559 Blocks 和 Vasya and Binary String CodeForces - 1107E (dp OR 记忆化搜索)

UVA - 10559 Blocks 题意:消消乐,每次连续相同的可以消除,分数加上长度的平方,问最多可以获得几分全部消完 题解: 区间dp + 记忆化搜索 dp[i][j][k] : (区间 [i,  j] 后面带上一段和 j 颜色相同的且长度为 k )的消消乐最大积分 1.消最后一段颜色和 j 颜色相同的 dp[i][j][k] <-- dp[i][j-1][0] + (k+1)^2 2.对于i <= l < j, 如果 l 和 j 的颜色相同, 那么可以把 [l+1, j-1]消掉

UVA - 10559 Blocks

题文:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1500(或者见紫书) 题解: 因为这个题目我们用区间的dp常见套路设dp[i][j]表示处理到i~j的最大贡献不能靠枚举断点进行转移,所以我们要更细致的描述这个状态.设dp[i][j][k],表示把第i个区间和第j个区间合并,并且由于前面的消除有k个与区间j的颜色相同的方块接着j后面的

uva 10559

记忆话搜索 DP 看了网上题解  状态方程真是巧妙 orz #include <cstdio> #include <cstdlib> #include <cmath> #include <set> #include <stack> #include <vector> #include <sstream> #include <cstring> #include <string> #include &l

uva 10743 - Blocks on Blocks(矩阵快速幂)

题目链接:uva 10743 - Blocks on Blocks 题目大意:问说n联骨牌有多少种,旋转镜像后相同不算同一组,一行的格子必须连续,如果答案大于10000,输出后四位. 解题思路:想了一下午的递推式,实在受不了,把推出的序列在网上搜了一下,有公式ai=5?ai?1?7?ai?2+4?ai?3 (i≥5) PS:哪位神人知道怎么推出来的请留言我,大恩不言谢~ #include <cstdio> #include <cstring> #include <algori

poj 1390 Blocks (动态规划)

Blocks Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 4318   Accepted: 1745 Description Some of you may have played a game called 'Blocks'. There are n blocks in a row, each box has a color. Here is an example: Gold, Silver, Silver, Sil

uva 116(动态规划起步第三天 DAG)

一道比较简单的动态规划的题,求从第一列的任何位置 到达最后一列 和的最小值. 所以这个状态可以是 列,在每一列有三种决策,直行,右上,右下.DP[i][j] 表示在第i行,j列到达最后一列的最小支出. 那么有了状态,我们可以进行转移,DP[i][j] = min{DP[i + 1][j + 1],DP[i][j + 1],DP[i - 1][j + 1]} + a[i][j];(跟数字三角形差不多) 1 #include <iostream> 2 #include <cstdio>

UVa 10365 - Blocks

題目:給你n個1*1*1的小立方體,把他們拼成一個長繁體,求最小的表面積. 分析:簡單題,枚舉.數據較小直接枚舉長款計算髙即可,打表計算查詢輸出. 說明:三個值越接近越好,╮(╯▽╰)╭. #include <algorithm> #include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #include <cmath> using name

Uva 10559 消除方块

题意: 每次可以选择一个区间(连续相同的序列)消除,得分为 len*len:问最大得分. 分析: 很容易想到是区间DP,但是不像普通的区间DP一样切割方式~~~ 如果定义 d[ i ][ j ] 区间,那么在里面切割,将有两个部分,而且中间的要连续相等,连续相等的区间可能还要枚举,加上 判断连续相等,可能会时间超,而且不是就算枚举了,剩下的还要合并,确实麻烦. 一种新的区间DP状态定义: d[i][j][k] 区间 i ~ j 后面继续加 k 个字符(与 j 相同)的最优解. 那么答案是: d[

uva 12563(动态规划起步第三天 01背包变形)

谈到背包,大家肯定都熟悉,我就不多讲,而这题挺有意思.DP[i][j] 表示前 i 首歌在j时间内唱的最多曲目: 状态有了,那么怎么转移呢? DP[i][j] = max{DP[i - 1][j],DP[i - 1][j - t[i]] + 1}; 但是此题还有时间.所以如果初始化为0的话,按照平常背包的代码,很难求出最长时间. 所以我们初始化为-1,且-1时不计算,那么这就避免了01背包的情况: 是不是觉得很像01背包的恰好装满情况.对,当然可以初始化为-无穷: 1 #include <ios