LightOJ - 1422 Halloween Costumes (区间DP)

题目链接:http://lightoj.com/volume_showproblem.php?problem=1422

题目大意:有n个地方,每个地方要穿一种衣服,衣服可以嵌套穿,一旦脱下的衣服不能再穿,除非穿同样的一件新的,问在满足题目要求的穿衣顺序下最少需要准备几件衣服

Sample Input

2

4

1 2 1 2

7

1 2 1 1 3 2 1

Sample Output

Case 1: 3

Case 2: 4

emmmm,区间DP。。。。别问我为什么QAQ,定义状态为$dp[i][j]$表示区间$[i,j]$最少所需要的衣服,很容易知道我们当转移的时候如果两边所需要的衣服一样,那么状态就变成了:$dp[l][r]=dp[l][r-1]$也就是说我可以直接将$l$所需要的衣服穿在最里面,这样就可以省下一件了。接下来就是比较常见的区间转移过程了:$dp[l][r]=min(dp[l][r],dp[l][mid]+dp[mid+1][r])$

以下是AC代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;

const int mac=150;
const int inf=1e8+10;

int a[mac],dp[mac][mac];

int main()
{
    int t,Case=0,n;
    scanf ("%d",&t);
    while (t--){
        scanf ("%d",&n);
        for (int i=1; i<=n; i++)
            scanf ("%d",&a[i]);
        for (int i=1; i<=n; i++)
            for (int j=i; j<=n; j++)
                dp[i][j]=inf;
        for (int i=1; i<=n; i++) dp[i][i]=1;
        for (int len=2; len<=n; len++)
            for (int l=1; l+len-1<=n; l++){
                int r=l+len-1;
                if (a[l]==a[r]) dp[l][r]=dp[l][r-1];
                for (int mid=l; mid<=r; mid++)
                    dp[l][r]=min(dp[l][r],dp[l][mid]+dp[mid+1][r]);
            }
        printf("Case %d: %d\n",++Case,dp[1][n]);
    }

    return 0;
}

 

posted @ 2020-07-07 23:43  lonely_wind  阅读(156)  评论(0编辑  收藏  举报