题目链接:
LightOJ 1422 Halloween Costumes
题意:
需要去参加
n
个聚会,每个聚会可能需要穿不同的衣服,用数字编号表示(
数据范围:
n≤100
分析:
先解释下样例。
n=41 2 1 2
意思是第一场和第三场聚会需要穿1号衣服,第二场和第四场聚会需要穿2号衣服,那么可以选择在第一场聚会时穿上1号衣服,在第二场聚会时在1号衣服外面套上2号衣服,在第三场聚会时脱下外面的2号衣服,然后第四场聚会时在套上一件新的2号衣服,那么总共至少3件衣服。
区间
dp
。
用
dp[i][j]
表示从第
i
场聚会到第
dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j])(k∈[i,j))
如果data[i]=data[j],则:dp[i][j]−−.
因为在得到区间 [i,j] 的状态时需要知道区间 [k,j] 状态的最优解并且 i≤k ,所以关于 i 的循环应是
初始化: dp[i][j]=inf,dp[i][i]=1 。
时间复杂度: O(n3)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <climits>
#include <cmath>
#include <ctime>
#include <cassert>
#define IOS ios_base::sync_with_stdio(0); cin.tie(0);
using namespace std;
typedef long long ll;
const int MAX_N = 110;
const int inf = 0x3f3f3f3f;
int T, n, cases = 0;
int data[MAX_N], dp[MAX_N][MAX_N];
int main()
{
scanf("%d", &T);
while (T--) {
scanf("%d", &n);
for (int i = 0; i < n; ++i) {
scanf("%d", &data[i]);
}
for(int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
dp[i][j] = inf;
}
}
for (int i = 0; i < n; ++i) { dp[i][i] = 1; }
for (int i = n - 1; i >= 0; --i) {
for (int j = i; j < n; ++j) {
for (int k = i; k < j; ++k) {
dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j]);
}
if(i != j && data[i] == data[j]) dp[i][j]--;
//if(dp[i][j] == 0) dp[i][j] = 1;
// printf("dp[%d][%d] = %d\n", i, j, dp[i][j]);
}
}
printf("Case %d: %d\n", ++cases, dp[0][n - 1]);
}
return 0;
}