【YBTOJ】【UVA10559】方块消除 Blocks
【YBTOJ】【UVA10559】方块消除 Blocks
链接:
题目大意:
有 \(n\) 个带有颜色的方块,没消除一段长度为x的连续的相同颜色的方块可以得到 \(x^2\) 的分数,让你用一种最优的顺序消除所有方块使得得分最多。
正文:
考虑区间 DP。若用一般状态 \(f_{l,r}\) 很难算、不方便,就再设一维:\(f_{l,r,k}\) 表示 \([l,r]\) 后,还有 \(k\) 个与 \(r\) 颜色相同的块的最大得分。
就有两种转移的方法:
\[\left.\begin{matrix}
f_{i,j-1,0} + (k+1)^2 &\rightarrow &f_{i,j,k} \\
f_{i,p,k+1} + f_{p+1,j-1,0} &\rightarrow &f_{i,j,k}
\end{matrix}\right\}\]
其中 \(p\) 表示在 \([l,r)\) 中与 \(r\) 颜色相同的块。
代码:
const int N = 210;
inline ll Read()
{
ll x = 0, f = 1;
char c = getchar();
while (c != '-' && (c < '0' || c > '9')) c = getchar();
if (c == '-') f = -f, c = getchar();
while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0', c = getchar();
return x * f;
}
int t, n;
int a[N], nxt[N], head[N];
ll f[N][N][N];
ll dfs(int i, int j, int k)
{
if (i > j) return 0;
if (f[i][j][k]) return f[i][j][k];
ll ans = dfs(i, j - 1, 0) + (k + 1) * (k + 1);
for (int p = nxt[j]; p >= i; p = nxt[p])
ans = max(ans, dfs(i, p, k + 1) + dfs(p + 1, j - 1, 0));
return f[i][j][k] = ans;
}
int main()
{
t = Read();
for (int T = 1; T <= t; T++)
{
memset (f, 0, sizeof f);
memset (nxt, 0, sizeof nxt);
memset (head, 0, sizeof head);
n = Read();
for (int i = 1; i <= n; i++)
a[i] = Read(),
nxt[i] = head[a[i]], head[a[i]] = i;
printf ("Case %d: %d\n", T, dfs(1, n, 0));
}
return 0;
}