题解
题目大意 一个人参加舞会 第i个舞会需要穿着a[i]颜色的衣服 他可以同时穿着多件衣服到时候再脱掉 但是脱掉的衣服不能在穿上 问最少需要多少衣服
使用区间dp求解 d[i][j]表示从i到j区间的舞会需要的最少衣服数量 考虑
单独一个舞会需要的数量为1
如果一个区间d[i][j] a[i]==a[j]也就是第一场舞会的和最后一场的衣服一样则d[i][j]一定等于d[i][j - 1]因为最后一个一定能穿第一场的衣服 第一场的衣服全程也不会脱掉 因为他前面没衣服了脱掉无意义 即d[i][j] = d[i][j - 1]
最后遍历区间中间点合并区间d[i][j] = min(d[i][j], d[i][k] + d[k + 1][j])
AC代码
#include <stdio.h>
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int MAXN = 110;
int a[MAXN];
int d[MAXN][MAXN];
int main()
{
#ifdef LOCAL
freopen("C:/input.txt", "r", stdin);
#endif
int T;
cin >> T;
for (int ti = 1; ti <= T; ti++)
{
int N;
cin >> N;
for (int i = 1; i <= N; i++)
scanf("%d", &a[i]);
memset(d, 0x3f, sizeof(d));
for (int i = 1; i <= N; i++)
d[i][i] = 1; //单个为1
for (int l = 2; l <= N; l++)
for (int i = 1; i + l - 1 <= N; i++)
{
int j = i + l - 1;
if (a[i] == a[j]) //区间前后相等 最后一个一定不会造成贡献
d[i][j] = d[i][j - 1]; //从小区间转移过来 第一件不可能脱掉 最后一个肯定可以用第一件
for (int k = i; k < j; k++) //合并区间
d[i][j] = min(d[i][j], d[i][k] + d[k + 1][j]);
}
printf("Case %d: %d\n", ti, d[1][N]);
}
return 0;
}