消木块

简介: 消木块

你们中的一些人可能玩过一个叫做消木块的游戏。

n 个木块排成一列,每个木块都有一个颜色。

例如下图中木块的颜色分别为:金,银,银,银,银,铜,铜,铜,金。

1390_1.jpg

每次,你都可以点击一个木块,这样被点击的木块以及和它相邻并且同色的木块就会消除。

如果一次性消除了 k 个木块,那么就会得到 k×k 分。

例如下图所示,点击银色木块,四个木块被消去,得到 16 分。

1390_2.jpg

给定你一个游戏初始状态,请你求出最高得分是多少。

输入格式
第一行包含整数 t,表示共有 t 组测试数据。

每组数据第一行包含整数 n,表示共有 n 个木块。

第二行包含 n 个整数,表示 n 个木块的颜色。

代表木块颜色的整数范围是 1∼n。

输出格式
每组数据输出一个结果,每个结果占一行。

输出格式为 Case x: y,其中 x 为数据组别编号,从 1 开始,y 为结果。

数据范围
1≤n≤200
输入样例:
2
9
1 2 2 2 2 3 3 3 1
1
1
输出样例:
Case 1: 29
Case 2: 1

加状态的区间dp
图解



#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <sstream>
#include <iomanip>
#include <cmath>
#include <bitset>
#include <assert.h>

using namespace std;
typedef long long llong;
typedef set<int>::iterator ssii;

#define Cmp(a, b) memcmp(a, b, sizeof(b))
#define Cpy(a, b) memcpy(a, b, sizeof(a))
#define Set(a, v) memset(a, v, sizeof(a))
#define debug(x) cout << #x << ": " << x << endl
#define _forS(i, l, r) for(set<int>::iterator i = (l); i != (r); i++)
#define _rep(i, l, r) for(int i = (l); i <= (r); i++)
#define _for(i, l, r) for(int i = (l); i < (r); i++)
#define _forDown(i, l, r) for(int i = (l); i >= r; i--)
#define debug_(ch, i) printf(#ch"[%d]: %d\n", i, ch[i])
#define debug_m(mp, p) printf(#mp"[%d]: %d\n", p->first, p->second)
#define debugS(str) cout << "dbg: " << str << endl;
#define debugArr(arr, x, y) _for(i, 0, x) { _for(j, 0, y) printf("%c", arr[i][j]); printf("\n"); }
#define _forPlus(i, l, d, r) for(int i = (l); i + d < (r); i++)
#define lowbit(i) (i & (-i))

const int maxn = 200 + 10;
int f[maxn][maxn][maxn];
int A[maxn];
int N;

void init() {
    Set(f, -1);
}

int dp(int i, int j, int k) {
    if(i > j) return 0;
    int& ans = f[i][j][k];
    if(i == j) return ans = (1 + k) * (1 + k);
    if(ans >= 0) return ans;

    int p = j;
    while (p >= i && A[p] == A[j]) p--;
    p++;

    ans = dp(i, p-1, 0) + (k + j-p+1) * (k + j-p+1);
    _for(q, i, p) {
        if(A[q] == A[j] && A[q+1] != A[q]) {
            ans = max(ans, dp(i, q, k+j-p+1) + dp(q+1, p-1, 0));
        }
    }

    return ans;
}

int main() {
    freopen("input.txt", "r", stdin);
    int T;
    scanf("%d", &T);
    _rep(kase, 1, T) {
        printf("Case %d: ", kase);
        scanf("%d", &N);
        _rep(i, 1, N) scanf("%d", &A[i]);
        init();

        // then dp()
        printf("%d\n", dp(1, N, 0));
    }
}
目录
相关文章
|
6月前
|
流计算
oninput和onchange事件的区别是什么
oninput和onchange事件的区别是什么
记录一次button闪烁问题
记录一次button闪烁问题
66 0
|
移动开发 前端开发 JavaScript
antd popover定位不准闪跳解决+自己实现popover库
我在写H5-dooring时,发现我们用的popover会发生闪跳,而且第一次闪跳就算了,每次还会有另一个方向的闪跳。 于是我大概百度了下,基本都说需要给固定宽高即可,让后试了下发现没用,就算触发组件和弹窗元素都给了宽高,也一样闪跳。由于antd的popover底层的实现是套其他第三方的库,第三方库又用到了其他的前端组件, 所以锁心自己实现一个。
1129 0
|
3月前
oninput和onchange事件有什么区别?
oninput和onchange事件有什么区别? 最新推荐文章于 2024-08-14 15:45:18 发布
117 0
|
6月前
|
JavaScript 开发者
【掰开揉碎】深入了解 @tap 和 @click
【掰开揉碎】深入了解 @tap 和 @click
192 0
|
6月前
失焦事件和点击事件
失焦事件和点击事件
39 1
|
流计算
oninput和onchange事件有什么区别
oninput和onchange事件有什么区别
95 0
|
JSON 数据格式
onchange事件
onchange事件
59 0
|
数据可视化
UGUI系列-Button绑定事件的多种实现
今天分享一下UGUI Button绑定事件的几种方法,以及优点和缺点 有哪些地方不懂的小伙伴也可以联系我的QQ,我的QQ就在博客链接中隐藏着,看能不能找到咯