【每日一题(34)】Halloween Costumes LightOJ-1422

Halloween Costumes LightOJ-1422

Gappu has a very busy weekend ahead of him. Because, next weekend is Halloween, and he is planning to attend as many parties as he can. Since it’s Halloween, these parties are all costume parties, Gappu always selects his costumes in such a way that it blends with his friends, that is, when he is attending the party, arranged by his comic-book-fan friends, he will go with the costume of Superman, but when the party is arranged contest-buddies, he would go with the costume of ‘Chinese Postman’.

Since he is going to attend a number of parties on the Halloween night, and wear costumes accordingly, he will be changing his costumes a number of times. So, to make things a little easier, he may put on costumes one over another (that is he may wear the uniform for the postman, over the superman costume). Before each party he can take off some of the costumes, or wear a new one. That is, if he is wearing the Postman uniform over the Superman costume, and wants to go to a party in Superman costume, he can take off the Postman uniform, or he can wear a new Superman uniform. But, keep in mind that, Gappu doesn’t like to wear dresses without cleaning them first, so, after taking off the Postman uniform, he cannot use that again in the Halloween night, if he needs the Postman costume again, he will have to use a new one. He can take off any number of costumes, and if he takes off k of the costumes, that will be the last k ones (e.g. if he wears costume A before costume B, to take off A, first he has to remove B).

Given the parties and the costumes, find the minimum number of costumes Gappu will need in the Halloween night.

Input

Input starts with an integer T (≤ 200), denoting the number of test cases.

Each case starts with a line containing an integer N (1 ≤ N ≤ 100) denoting the number of parties. Next line contains N integers, where the ith integer ci (1 ≤ ci ≤ 100) denotes the costume he will be wearing in party i. He will attend party 1 first, then party 2, and so on.

Output

For each case, print the case number and the minimum number of required costumes.

Sample Input

2
4
1 2 1 2
7
1 2 1 1 3 2 1

Sample Output

Case 1: 3
Case 2: 4

题解

解释一下题意:题目说,那个人要去参加很多场万圣节派对,而且很多排队的主题不同,也意味着穿的衣服也可能不同。
但是这个小伙子又忙又懒,他可以穿很多层衣服去参加很多场排队。例如有一场编号为1,2的派对,他可以里面穿着2的衣服,外面穿着1的衣服。去到参加2号排队时,把外面的衣服脱了就行。
但是这个小伙子不喜欢穿脏衣服,也不会洗衣服。所以脱下来的衣服不能再穿上去。
于是题目的问题是,给定不同编号的派对,问你他需要准备至少多少件衣服。

这个题是区间dp的问题,所以我们可以用形似

dp[i][j] = min{dp[i][j],dp[i][k] + dp[k + 1][j] + w[i][j]};

的状态转移式来写。

我们用dp[i][j]表示从第i到第j场需要准备的衣服
于是,当在第j场时,如果他新穿一件衣服,即dp[i][j] = dp[i][j - 1] + 1;
如果,如果他不新穿一件,就要找到与第j场穿同样衣服的场次k。
当找到穿同意衣服的场次k,意味着他的第j场的衣服要在第k场保留到第j场。
即在第k场后穿的衣服,要在第j场前全部脱掉,这样子才可以把第j场的衣服漏出来;
即 dp[i][j] = dp[i][k] + dp[k + 1][j - 1];

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include<iostream>
#include<cstdio>
using namespace std;
#define maxn 105
int dp[maxn][maxn],a[maxn];
int main(){
int T;
cin >> T;
for(int x = 1; x <= T; x++){
cin >> a[0];
for(int i = 1;i <= a[0]; i++){
cin >> a[i];
fill(dp[i],dp[i] + a[0] + 1, 0);
dp[i][i] = 1;
}
for(int len = 2; len <= a[0]; len++){
for(int i = 1,j;(j = i + len - 1) <= a[0]; i++){
dp[i][j] = dp[i][j - 1] + 1;
for(int k = i;k < j; k++){
if(a[k] == a[j]){
dp[i][j] = min(dp[i][j],dp[i][k] + dp[k + 1][j - 1]);
}
}
}
}
cout << "Case " << x << ": " << dp[1][a[0]] << endl;
}

return 0;
}