• LightOj 1422 Halloween Costumes(区间DP)


    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

    从左端开始比较:

    #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
    ",++cas,dp[1][n]);
    
        }
        return 0;
    }

    从右端开始比较

    #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
    ",++cas,dp[1][n]);
    
        }
        return 0;
    }
    
  • 相关阅读:
    基于 Docker 的现代软件供应链
    Java 性能调优指南之 Java 集合概览
    Docker 网络基础介绍
    选择 Java 编写 iOS 与 安卓 App的八大理由
    使用Babel和ES7创建JavaScript模块
    Java 8方法引用使用指南
    软件可扩展性:来自星巴克的经验
    Docker 监控之 SaaS 解决方案
    如何高效的阅读uni-app框架?(建议收藏)
    如何高效的阅读uni-app框架?(建议收藏)
  • 原文地址:https://www.cnblogs.com/dacc123/p/8228755.html
Copyright © 2020-2023  润新知