LightOJ

题目链接:传送门

题目大意:要参加聚会,对应聚会要穿对应衣服,衣服可以套着穿,也可以脱下来,但脱下来之后不能再穿,问参加完所有聚会至少需要几件衣服?

题目思路:区间DP

     一开始自己没有想出来状态转移方程,但是想到了左右区间如果边界相等的时候衣服数目应该-1,可以少穿一件。其实拓展一点就是更新

     方程的一部分了。对于区间 [l,r] ,如果r处的值==l处的值(要求穿的衣服相同),那么区间 [l,r]所穿的最少衣服等于区间 [l,r-1] 所穿最少衣服,

     因为 l 是起点,也就是说最里面穿的衣服是 l 对应的值,从 l 到 r 无论怎么更新,最里面的那件衣服始终不用脱掉,那么到 r 时候,至少有一种

     情况,也就是脱其他所有衣服,只剩 l 时,这时候也是满足条件的。对应的转移的方程 if(a[l]==a[r]) dp[l][r]=dp[l][r-1];

     然后对于其他区间,也就相同于普通区间DP转移。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <stack>
#include <cctype>
#include <queue>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <climits>
#define lson root<<1,l,mid
#define rson root<<1|1,mid+1,r
#define fi first
#define se second
#define ping(x,y) ((x-y)*(x-y))
#define mst(x,y) memset(x,y,sizeof(x))
#define mcp(x,y) memcpy(x,y,sizeof(y))
using namespace std;
#define gamma 0.5772156649015328606065120
#define MOD 1000000007
#define inf 0x3f3f3f3f
#define N 100005
#define maxn 100005
typedef pair<int,int> PII;
typedef long long LL;

int n,m,a[105],dp[105][105];

int main(){
    int i,j,group,Case=0;
    scanf("%d",&group);
    while(group--){
        mst(dp,inf);
        scanf("%d",&n);
        for(i=1;i<=n;++i){
            scanf("%d",&a[i]);
            dp[i][i]=1;
        }
        for(int p=2;p<=n;++p)
        for(int i=1;i<n;++i){
            j=i+p-1;
            if(j>n)break;
            if(a[i]==a[j])dp[i][j]=dp[i][j-1]; ///***
            for(int k=i;k<j;++k){
                dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]);
                ///这里如果a[k]==a[k+1]不需要处理
                ///因为在转移之前已经处理过了
            }
        }
        printf("Case %d: %d
",++Case,dp[1][n]);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/Kurokey/p/5644815.html