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后面的最大贡献。

  那么转移我们可以考虑1.直接将j区间和k消除。dp[i][j][k]=dp[i][j-1][0]+(len[j]+k)^2。2.考虑将j和前面的某个颜色相同的区间合并,所以要消除中间的某几段区间。

既:dp[l][r][k]=dp[i+1,][r-1][0]+dp[l][i][k+len[r]]。的确这个题目还是自己好好消化吧,是道经典的dp题目。

代码:

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<algorithm>
#include<cstring>
using namespace std;
int color[1000],len[1000],n,t;
int shu[1000],dp[300][300][300];

void cl(){
    memset(color,0,sizeof(color));
    memset(len,0,sizeof(len));
    memset(shu,0,sizeof(shu));
    memset(dp,0,sizeof(dp));
}

int dfs(int l,int r,int k){
    if(l>r) return 0;
    if(l==r) return (len[l]+k)*(len[l]+k);
    if(dp[l][r][k]!=0) return dp[l][r][k];
    dp[l][r][k]=dfs(l,r-1,0)+(len[r]+k)*(len[r]+k);
    for(int i=l;i<r;i++){
        if(color[i]==color[r])
        dp[l][r][k]=max(dp[l][r][k],dfs(i+1,r-1,0)+dfs(l,i,k+len[r]));
    }
    return dp[l][r][k];
}

int main(){
    scanf("%d",&t);
    for(int hh=1;hh<=t;hh++){
        scanf("%d",&n);
        cl();
        for(int i=1;i<=n;i++) scanf("%d",&shu[i]);
        int star=1,now=1,num=0,lenn=0;
        while(now<=n){
            while(shu[star]==shu[now]){
                now++,lenn++;
            }
            color[++num]=shu[star];
            len[num]=lenn;
            lenn=0;star=now;
        }
        printf("Case %d: %d\n",hh,dfs(1,num,0));
    }
}
时间: 2024-08-08 14:07:21

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 - 动态规划

题目传送门 传送门 题目大意 有$n$个方块排成一排,每次可以选择一段连续相同的颜色的方块消去并将两端拼接起来,设消去的长度为$x$,那么可以得到$x^2$的分数.问消去所有方块后的最高得分. 标算的状态设计感觉比较神仙. 设$f_{l, r, k}$表示考虑到第$l$个方块到第$r$个方块,在第$r$个方块后面有$k$个和第$r$个方块的颜色一样的方块,将这些方块都消去能够得到的最大的分数. 首先不难发现每次消除一定消除的是当前一个极大颜色相同的连续段. 转移的时候考虑$r$所在原序列的一个极

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

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[

10559 - Blocks(方块消除|DP)

该题乍一看和矩阵链乘很相似,可是有一个不同之处就是该题可以拼接 .   为了达到这个目的,我们不得不拓展维度d[i][j][k],用一个k表示最右边拼接了k个和a[j]相同颜色的方块. 问题的关键在于拼接,当右边存在一个q < p 且 a[q] == q[j] && a[q] != a[q+1] 时,可以拼接,要注意,所有满足这个条件的q都应该递归求解,因为哪一部分拼接起来更好,是不一定的 . 细节见代码: #include<bits/stdc++.h> using na

【UVA】434-Matty&amp;#39;s Blocks

一道非常easy想复杂的题,给出主视图和右视图,计算最少能用几个正方体组成相应的视图,以及最多还能加几块正方体. 求最多加入事实上就是求出最多的正方体数减去最少的,主要就是最少的不好求. 一開始各种模拟就是不正确,之后发现,仅仅须要统计两个视图的高度个数就能够了(简直了) 14390495 434 Matty's Blocks Accepted C++ 0.016 2014-10-21 11:35:11 #include<cstdio> #include<cstring> #inc

【UVA】434-Matty&#39;s Blocks

一道很容易想复杂的题,给出主视图和右视图,计算最少能用几个正方体组成对应的视图,以及最多还能加几块正方体. 求最多添加其实就是求出最多的正方体数减去最少的,主要就是最少的不好求. 一开始各种模拟就是不对,之后发现,只需要统计两个视图的高度个数就可以了(简直了) 14390495 434 Matty's Blocks Accepted C++ 0.016 2014-10-21 11:35:11 #include<cstdio> #include<cstring> #include&l