题目链接:
http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=27130
题意:
一个人赶几场舞会,每场舞会穿的衣服不一样。规定衣服可脱,重新穿时算新的一件。因为可以几件衣服套在一起,问最少用几件新衣服。
思路:
在解释中理清思路。dp[i][j]为第i到第j场需要穿的最少衣服数目。对于每个dp,初始化为dp[i][j] = 1 +dp[i+1][j],然后在i+1到j的区间里找最优值k。若data[k] == data[i],则dp = gmin(dp[i+1][k-1]+dp[k][j]),否则dp[i][j] = gmin(dp[i+1][k-1]+dp[k][j]+1)。(即考虑假设k场与i场的衣服相同,则假设i场衣服不脱,一直穿到k场,并且由于动态规划已经得到最优解的缘故,dp[i+1][k-1]已经得到最优值)。原本思考的时候想到变换以哪件衣服为底时会发生翻转问题,看完题解发现是不需要换底的。指需要加底,即假设一开始就存在哪些衣服、它们的顺序就好。
源码:
#include <bits/stdc++.h>
#define gmin(a,b) a<b?a:b
const int MAXN = 100+5;
int dp[MAXN][MAXN];
int data[MAXN];
int main()
{
int t;
scanf("%d",&t);
for(int i=1; i<=t; i++){
int n;
scanf("%d",&n);
for(int i=0; i<n; i++){
scanf("%d",&data[i]);
}
memset(dp,0,sizeof(dp));
for(int i=0; i<n; i++)
dp[i][i] = 1;
for(int i=1; i<=n; i++){///length
for(int j=n-1; j>=0; j--){///start point
int st = j-i;
if(st < 0)
break;
dp[st][j] = 1 + dp[st+1][j];
for(int k = st+1; k<=j;k++){
if(data[k] == data[st]){
dp[st][j] =gmin(dp[st][j], dp[st+1][k-1] + dp[k][j]);
}
}
}
}
// for(int i=0; i<n; i++){
// for(int j=0; j<n; j++)
// printf("%d",dp[i][j]);
// printf("\n");
// }
printf("Case %d: %d\n",i,dp[0][n-1]);
}
return 0;
}