消木块

简介: 消木块

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

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));
    }
}
目录
相关文章
|
5月前
|
JavaScript 前端开发
事件绑定(onclick,onfocus,onblur)
事件绑定(onclick,onfocus,onblur)
65 0
|
5月前
|
流计算
oninput和onchange事件的区别是什么
oninput和onchange事件的区别是什么
|
2月前
oninput和onchange事件有什么区别?
oninput和onchange事件有什么区别? 最新推荐文章于 2024-08-14 15:45:18 发布
70 0
|
5月前
|
JavaScript 前端开发
oninput 和 onchange 事件的区别
oninput 和 onchange 事件的区别
53 9
|
5月前
oninput事件和onchange事件的区别?
oninput事件和onchange事件的区别?
|
5月前
|
JavaScript
oninput 和 onchange 事件有什么区别
oninput 和 onchange 事件有什么区别
|
5月前
|
JavaScript 开发者
【掰开揉碎】深入了解 @tap 和 @click
【掰开揉碎】深入了解 @tap 和 @click
139 0
|
5月前
失焦事件和点击事件
失焦事件和点击事件
34 1
|
11月前
|
流计算
oninput和onchange事件有什么区别
oninput和onchange事件有什么区别
72 0
|
JSON 数据格式
onchange事件
onchange事件
57 0