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;
}

 

 

 

 

posted on 2013-04-29 22:52  kuangbin  阅读(1600)  评论(0编辑  收藏  举报

导航

JAVASCRIPT: