区间dp入门(light oj 1422 - Halloween Costumes)

给你n天需要穿的衣服的样式,每次可以套着穿衣服,脱掉的衣服就不能再用了(可以再穿,但算cost),问至少要带多少条衣服才能参加所有宴会

第一步:初始化dp[i][i]为1意思就是这天换新的,从i到i最小换衣数

第二步:j从2到n,i从1到j(取不到)

先假设从i到j,第j天换衣服则dp[i][j]=dp[i][j-1]+1;

假设有k为[i,j),看第k天服装类型是否与j相同,若相同则min(dp[i][j],dp[i][k]+dp[k+1][j-1])后面一部分表示需要脱下了的

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#define maxn 105
#define MAXN 100005
#define mod 100000000
#define INF 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-6
typedef long long ll;
using namespace std;
 
int n,m,ans,cnt,tot;
int a[maxn],dp[maxn][maxn];
 
int main()
{
    int i,j,t,test=0;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
        }
        memset(dp,0,sizeof(dp));//表示从i-j所需最小数量;
        for(i=1;i<=n;i++) dp[i][i]=1;//从i-i为1,表示每天都换的初始化情况;
        for(j=2;j<=n;j++)
        {
            for(i=1;i<j;i++)//从i->j
            {
                dp[i][j]=dp[i][j-1]+1;//第j天再穿一件
                for(int k=i;k<j;k++)
                {
                    if(a[k]==a[j]) dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j-1]);
                }//如果有i-j中有与j相同的类型,进行区间dp;
            }
        }
        ans=dp[1][n];
        printf("Case %d: %d\n",++test,ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/lanshan1111/article/details/82183946