LightOJ

来源:互联网 发布:雅马哈网络经销商查询 编辑:程序博客网 时间:2024/06/07 21:38

Halloween Costumes

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

题意:

一个人要去N场party,每场有要求出席的衣服种类,穿上的衣服可以选择不脱和脱,但是脱了以后不能穿回,且类似于栈,要脱掉里面的衣服必须把这件衣服之前的衣服全部脱掉。
题目要求很类似栈,要露出以前的衣服,必须要目标衣服之前的所有衣服
对于每一件要出席的衣服都有穿新和不穿用以前的两种状态
即:可以选择上一次穿这次也穿,上一次穿这次不穿
共两种状态

正常穿衣服方式:按时间顺序考虑

对于区间[I,J],把a[J]作为第J天穿的衣服,那么
F[I][J]中的A[J]这件衣服一定穿在身上,因为要符合第J天的要求,而且还没有到J+1天,衣服不用换
下面考虑区间[I,J]中第J件衣服穿不穿
第一种穿,那就是[I,J-1]的代价再加上新穿的衣服:
F[I][J]=F[I][J-1]+1;
第二种不穿,如果不穿,必须在[L,R]区间内找到一个K,使得A[K]==A[R],并且一直到R时刻,这一件都不脱掉,怎么保证?
F[I][J]=min{F[I,K]+F[K+1][J-1]},i<=k
为什么是I~K? 因为I~K保证了通过I~K这段时间后,保证了F[I+1][K]到第K天,还穿着A[K]这种颜色的衣服
然后把K+1~J-1之间这些数量的衣服脱掉就露出了A[K]==A[J]
这样递推保证了第J天能穿到符合条件的衣服,而且是最值
注:递推式可能不止一种形式,只要符合最值,和符合每一天的要求就可以,下面会见到例子
这种递推方式的标程地址:
http://blog.csdn.net/tobewhatyouwanttobe/article/details/36420755

有点反常,其实也很正常

对于每一个区间[I,J],每次想知道我要这次的衣服有没有贡献,也就是A[I]这件衣服有没有用
如果有用我想留着,下次可以不穿
每次去[I,J]区间里找A[I]==A[K],如果存在这种情况
那么和上文类似的
第一种形式:F[I][J]=min{ F[I][K-1]+dp[K+1][J]}
先计算了A[I]的代价,算入了从第I天开始到第K-1天穿的衣服,脱掉I+1~K-1部分,露出A[K]==A[I],因为相同A[K]不用重复算,之后的K+1~J一起算
第二种形式:F[I][J]=min{F[I+1][K-1]+F[K][J]}
I+1~K-1中间的衣服脱掉就是我第K天要穿的A[K]==A[I],然后第I天的A[I]移到了A[K]这一天来考虑,这样A[I]的代价不会重复算
第一种形式标程: http://blog.csdn.net/a664607530/article/details/52558851
第二种形式标程:
http://blog.csdn.net/fungyow/article/details/47358821

时间复杂度都是O(N^3)

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn=100+5;int dp[maxn][maxn],n,a[maxn],kase;int main(){  int T;  scanf("%d",&T);  while(T--)  {    scanf("%d",&n);    for(int i=1;i<=n;++i)scanf("%d",a+i);    for(int i=1;i<=n;++i)dp[i][i]=1;    for(int L=n-1;L>0;--L)    {      for(int R=L+1;R<=n;++R)      {        dp[L][R]=dp[L+1][R]+1;        for(int k=L+1;k<=R;++k)          if(a[L]==a[k])dp[L][R]=min(dp[L][R],dp[L+1][k-1]+dp[k][R]);      }    }    printf("Case %d: %d\n",++kase,dp[1][n]);  }  return 0;}