Light OJ 1422 - Halloween Costumes
题目链接:http://lightoj.com/volume_showproblem.php?problem=1422
很简单的区间DP的入门题。一开始这题想了很久就是想不出来。直到做了后面几道区间DP回过来终于想明白了。
区间DP可以使用记忆化搜索和直接DP的方法写。
这题的状态转移方程:
dp[i][j]=min(1+dp[i+1][j],dp[i+1][k-1]+dp[k][j]) ( a[i]==a[k] i<k<=j )
注意初始化。
/* * Light OJ 1422 - Halloween Costumes * http://lightoj.com/volume_showproblem.php?problem=1422 * 区间DP的思想。 * 比如要求解i到j,dp[i][j]. * 就是考虑i的衣服,一种是i的衣服只有在i使用,那么就是dp[i+1][j]+1件 * 然后再i+1~j中枚举k,如果a[i]==a[k].那么dp[i][j]=min(dp[i][j],dp[i+1][k-1]+dp[k][j]) * 注意因为i的衣服是可以使用多次的,所以不需要加1,是dp[k][j] * 思想很妙 */ #include <iostream> #include <stdio.h> #include <algorithm> #include <string.h> using namespace std; const int MAXN=110; int a[MAXN]; int dp[MAXN][MAXN]; int main() { int T; int n; scanf("%d",&T); int iCase=0; while(T--) { iCase++; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); memset(dp,0,sizeof(dp)); for(int i=1;i<=n;i++) for(int j=i;j<=n;j++) dp[i][j]=j-i+1; for(int i=n-1;i>=1;i--)//注意DP的顺序 for(int j=i+1;j<=n;j++) { dp[i][j]=dp[i+1][j]+1;//这个表示第i个的衣服在后面没有利用了 for(int k=i;k<=j;k++) if(a[i]==a[k])//用同一件 dp[i][j]=min(dp[i][j],dp[i+1][k-1]+dp[k][j]); } printf("Case %d: %d\n",iCase,dp[1][n]); } return 0; }
人一我百!人十我万!永不放弃~~~怀着自信的心,去追逐梦想