前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >LightOj 1422 Halloween Costumes(区间DP)

LightOj 1422 Halloween Costumes(区间DP)

作者头像
ShenduCC
发布2018-04-26 14:41:53
7630
发布2018-04-26 14:41:53
举报
文章被收录于专栏:算法修养

B - Halloween Costumes Time Limit:2000MS Memory Limit:32768KB 64bit IO Format:%lld & %llu Submit

Status

Practice

LightOJ 1422 Description Gappu has a very busy weekend ahead of him. Because, next weekend is Halloween, and he is planning to attend as many parties as he can. Since it’s Halloween, these parties are all costume parties, Gappu always selects his costumes in such a way that it blends with his friends, that is, when he is attending the party, arranged by his comic-book-fan friends, he will go with the costume of Superman, but when the party is arranged contest-buddies, he would go with the costume of ‘Chinese Postman’.

Since he is going to attend a number of parties on the Halloween night, and wear costumes accordingly, he will be changing his costumes a number of times. So, to make things a little easier, he may put on costumes one over another (that is he may wear the uniform for the postman, over the superman costume). Before each party he can take off some of the costumes, or wear a new one. That is, if he is wearing the Postman uniform over the Superman costume, and wants to go to a party in Superman costume, he can take off the Postman uniform, or he can wear a new Superman uniform. But, keep in mind that, Gappu doesn’t like to wear dresses without cleaning them first, so, after taking off the Postman uniform, he cannot use that again in the Halloween night, if he needs the Postman costume again, he will have to use a new one. He can take off any number of costumes, and if he takes off k of the costumes, that will be the last k ones (e.g. if he wears costume A before costume B, to take off A, first he has to remove B).

Given the parties and the costumes, find the minimum number of costumes Gappu will need in the Halloween night.

Input Input starts with an integer T (≤ 200), denoting the number of test cases.

Each case starts with a line containing an integer N(1 ≤ N ≤ 100) denoting the number of parties. Next line contains N integers, where the ith integer ci(1 ≤ ci ≤ 100) denotes the costume he will be wearing in party i. He will attend party 1 first, then party 2, and so on.

Output For each case, print the case number and the minimum number of required costumes.

Sample Input 2 4 1 2 1 2 7 1 2 1 1 3 2 1 Sample Output Case 1: 3 Case 2: 4 FAQ | About Virtual Judge | Forum | Discuss | Open Sourc

给一个问题 目标字符串 aaabbccaaa 一次只能在固定的区间内,将区间内的字符全都变成相同的字符。问你从一个空字符串到目标字符串最少几次可以变成。

解决方法和这道题目的解法是如出一辙。其实二者是完全一样的问题,一件穿了多少天就相当于在一个固定的区间覆盖了一个字符。

状态转移方程: dp[i][j]=dp[i+1][j]+1; dp[i][j]=min(dp[i][j],dp[i+1][k]+dp[k+1][j]).{k=i+1…j} 做动态规划的题目应该经常思考状态转移方程式怎么得来的。状态方程的意思理解还远远不够。

联系题目,最坏的结果是每遇到一天都新穿一件衣服。那么最优的情况是怎么得来的,自然是穿上一件衣服不用脱,因为在后来可以派上用场,这样就少新买一件衣服。 我们可以从区间的左端或者右端开始,和区间里的数比较,相等的话就划分区间。 这样的话可以得到全局最优解,注意递推的时候,一定要使子状态都计算过了。

关于区间DP,可以参照这个博客 http://blog.csdn.net/dacc123/article/details/50885903

从左端开始比较:

代码语言:javascript
复制
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
#include <math.h>
#include <stdio.h>

using namespace std;
int n;
int a[105];
int dp[105][105];
int main()
{
    int t;
    scanf("%d",&t);
    int cas=0;
    while(t--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
        }
        memset(dp,0,sizeof(dp));

        for(int i=n;i>=1;i--)
        {
            for(int j=i;j<=n;j++)
            {
                dp[i][j]=dp[i+1][j]+1;
                for(int k=i+1;k<=j;k++)
                {
                    if(a[i]==a[k])
                    dp[i][j]=min(dp[i][j],dp[i+1][k]+dp[k+1][j]);
                }
            }
        }
        printf("Case %d: %d\n",++cas,dp[1][n]);

    }
    return 0;
}

从右端开始比较

代码语言:javascript
复制
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
#include <math.h>
#include <stdio.h>

using namespace std;
int n;
int a[105];
int dp[105][105];
int main()
{
    int t;
    scanf("%d",&t);
    int cas=0;
    while(t--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
        }
        memset(dp,0,sizeof(dp));

        for(int l=0;l<n;l++)
        {
            for(int i=1;i+l<=n;i++)
            {
                int j=i+l;
                dp[i][j]=dp[i][j-1]+1;
                for(int k=i;k<=j-1;k++)
                {
                    if(a[j]==a[k])
                    dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j-1]);
                }
            }
        }
        printf("Case %d: %d\n",++cas,dp[1][n]);

    }
    return 0;
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016-03-26 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档