1. 程式人生 > >【每日一題(34)】Halloween Costumes LightOJ-1422

【每日一題(34)】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];

程式碼

#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;
}