light oj 1422(区间dp)

本文讨论了一个参加多个舞会时,如何以最少的衣物数量完成所有舞会的穿着问题。通过动态规划方法,优化策略实现最小衣物准备。

题意:一个人先后要参加n个舞会,已知他n个舞会要穿什么样的衣服。一件衣服他脱了以后,就不会再穿。他可以穿了一种衣服以后,在外面套另一种衣服,再在外面套另一种衣服........。问他最少要准备多少件衣服?

题解:原问题是参加完区间[1,n]的舞会,最少要准备多少件衣服。如果第1个舞会要穿的衣服和第i个舞会要穿的衣服相同,假设我们的策略是让第1个舞会和第i个舞会穿同一件衣服,那么区间[2,i-1] 的舞会所穿的衣服最后都要脱光。问题就变成求,区间[2,i-1]最少要准备多少件衣服,加上区间[i,r]最少要准备多少件衣服。原问题就转变成求子问题区间[2,i-1]和区间[i,r] 。当然我们也可以让第1个舞会穿的衣服以后都不穿,问题就转变成求子问题区间 [2,r] 最少要准备多少件衣服+1。显然不同的策略,会有不同的子问题,一定存在重叠子问题,而且子问题没有后效性。所以我们可以用动态规划来解决。


用dp[l][r] 表示参加[l,r] 的舞会最少要准备多少件衣服。转移就是:

dp[l][r]=min(dp[l][r],dp[l+1][r]+1)

如果第k件衣服和第l件衣服相同:

dp[l][r]=min(dp[l][r],dp[l+1][k-1]+dp[k][r]);

详情见代码:

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
#include<string>
#include<math.h>
#define nn 110
#define inff 0x3fffffff
#define eps 1e-8
typedef long long LL;
const LL inf64=LL(inff)*inff;
using namespace std;
int n;
int a[nn];
int dp[nn][nn];
int dfs(int l,int r)
{
    if(dp[l][r]!=-1)
        return dp[l][r];
    if(l>r)
        return 0;
    if(l==r)
        return dp[l][r]=1;
    dp[l][r]=inff;
    dp[l][r]=min(dp[l][r],dfs(l+1,r)+1);
    for(int i=l+1;i<=r;i++)
    {
        if(a[i]==a[l])
            dp[l][r]=min(dp[l][r],dfs(l+1,i-1)+dfs(i,r));
    }
    return dp[l][r];
}
int main()
{
    int i,t;
    scanf("%d",&t);
    int cas=1;
    while(t--)
    {
        scanf("%d",&n);
        for(i=1;i<=n;i++)
            scanf("%d",&a[i]);
        memset(dp,-1,sizeof(dp));
        printf("Case %d: ",cas++);
        printf("%d\n",dfs(1,n));
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值