LightOJ 1422 Halloween Costumes
Description
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个聚会,这n个聚会中分为几种,每种聚会都要穿特定的衣服。假如你现在穿着1号衣服(1号衣服里面还穿着2号衣服)在参加1号聚会,如果你一会要参加2号聚会,你可以把1号衣服脱了,露出来2号,
也可以再在外面套一件2号衣服。你有洁癖,脱下的衣服不能再穿上。PS:如果你现在穿着1 2 3(由里到外),你要参加3号聚会,如果你不想再往外面套衣服的话,你就要把1 2 号衣服同时脱掉。
问你最少需要准备几套衣服?
思路就是区间dp。假设dp[i][j]是区间i~j
我们先来一步步推导,首先如果无脑无思维安排的话dp[i][j]=j-i+1,是不?也就是区间长度。
下一步加入思维如果第i件衣服与以后的衣服没有相同的,dp[i][j]=dp[i+1][j]+1
如果存在k(i<k<=j),使得cloth[i]=cloth[k],我们就要考虑在k位置时是否重复用cloth[i],即dp[i][j]=min(dp[i][j],dp[i][k-1]+dp[k+1][j])
然后没了。
总结下就是先折腾好i+1~j这个区间的状态,然后再加上第i个,变成i~j,然后k从k+1跑到j,更新下dp数组的状态。
代码如下:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 using namespace std; 7 #define inf 0x3f3f3f3f 8 int dp[150][150]; 9 int cloth[150]; 10 int main() 11 { 12 int t,casee=0; 13 //freopen("de.txt","r",stdin); 14 scanf("%d",&t); 15 while (t--) 16 { 17 int n; 18 scanf("%d",&n); 19 for (int i=1;i<=n;++i) 20 scanf("%d",&cloth[i]); 21 memset(dp,0,sizeof dp); 22 23 for (int i=1;i<=n;++i) 24 for (int j=i;j<=n;++j) 25 dp[i][j]=j-i+1; 26 27 for (int i=n-1;i>=1;--i) 28 { 29 for (int j=i+1;j<=n;++j) 30 { 31 dp[i][j]=dp[i+1][j]+1; 32 for (int k=i+1;k<=j;++k) 33 { 34 if (cloth[i]==cloth[k]) 35 dp[i][j]=min(dp[i][j],dp[i][k-1]+dp[k+1][j]); 36 } 37 } 38 } 39 printf("Case %d: %d\n",++casee,dp[1][n]); 40 } 41 return 0; 42 }