LightOJ(1422)——Halloween Costumes

首先,我还是表扬一下自己,开始独立思考了,虽然说最后的想法是错误的,但是至少已经很接近了。所以,再接再厉吧!

题意:

现在那个人要去参加一个聚会,然后总共有n天,每天所要求穿的服饰的序号分别为c[i]。

这个人可以一次性穿上1件衣服,或者一次性脱下任意多件衣服。当然也可以在衣服外面套衣服。

并且如果这件衣服已经被脱下的话,那么它下次不能再次被穿上,如果我们还需要这件衣服的话,那么我们就只能重新再去买另外一件了。

最后问你,如果要参加完所有的派对,那么他所需要的最少的衣服数量是多少。

比如说第一个样例:

4

1 2 1 2

我们只需要先穿上1,然后再穿上2,再脱掉1,然后此时没有2的衣服了,所以我们还需要一件2的衣服,所以最后总共是需要3件衣服。

思路:

这题主要的难点是在于判断什么时候可以利用还存在的衣服。

定义dp[i][j]为i~j区间内所需要的最少衣服的数量。

感觉下面的思路很巧妙:

为什么从后面往前面推呢,我感觉就像是01背包为什么从后面往前面推一样,防止前面的影响后面的,(但是这里说实话我自己也不是很明白)所以我们这里进行倒着for。

1)dp[i][i]=1,这是初始化dp

2)当我们把第s件衣服单独拎出来的时候,那么就是dp[s][e]=dp[s+1][e]+1; 后面加1是因为这里还要多选1件。

3)然后枚举中间点k,当c[s]==c[k]时,这里的意思 是到第k天为止都穿着第i天的衣服,那么dp[s][e]=min(dp[s][e],dp[s+1][k-1]+dp[k][e]); 后面那个式子是因为我们这里不选择s这件衣服了,至于为什么要枚举到第k-1是因为,万一后面k~e区间中还存在c[k]==c[?],那么我们dp[k][e]就是要在这里面取最优的结果的,所以第一个区间是到k-1为止的。

推荐几个好懂的博客:http://www.cnblogs.com/neopenx/p/4050003.html        http://www.cnblogs.com/kuangbin/archive/2013/04/29/3051392.html

http://www.cnblogs.com/ziyi--caolu/archive/2013/08/04/3236035.html

#include
#include
#include
#include
using namespace std;
#define maxn 111
#define inf 99999999
int c[maxn];
int dp[maxn][maxn];
int main(){
	int T,j=1;
	scanf("%d",&T);
	while(T--){
		memset(dp,0,sizeof(dp));
		int n;
		scanf("%d",&n);
		for(int i=1;i<=n;i++){
			scanf("%d",&c[i]);
			dp[i][i]=1;
		}
		for(int s=n-1;s>=1;s--){
			for(int e=s+1;e<=n;e++){
				dp[s][e]=dp[s+1][e]+1;
				for(int k=s;k<=e;k++){
					if(c[s]==c[k]) dp[s][e]=min(dp[s][e],dp[s+1][k-1]+dp[k][e]);
				}
			}
		}
		printf("Case %d: %d\n",j++,dp[1][n]);
	}
}




你可能感兴趣的:(区间dp)