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;

}

 

 

 

 

你可能感兴趣的:(OS)