1045 Favorite Color Stripe (30分)

1 题目

1045 Favorite Color Stripe (30分)
Eva is trying to make her own color stripe out of a given one. She would like to keep only her favorite colors in her favorite order by cutting off those unwanted pieces and sewing the remaining parts together to form her favorite color stripe.

It is said that a normal human eye can distinguish about less than 200 different colors, so Eva’s favorite colors are limited. However the original stripe could be very long, and Eva would like to have the remaining favorite stripe with the maximum length. So she needs your help to find her the best result.

Note that the solution might not be unique, but you only have to tell her the maximum length. For example, given a stripe of colors {2 2 4 1 5 5 6 3 1 1 5 6}. If Eva’s favorite colors are given in her favorite order as {2 3 1 5 6}, then she has 4 possible best solutions {2 2 1 1 1 5 6}, {2 2 1 5 5 5 6}, {2 2 1 5 5 6 6}, and {2 2 3 1 1 5 6}.

Input Specification:
Each input file contains one test case. For each case, the first line contains a positive integer N (≤200) which is the total number of colors involved (and hence the colors are numbered from 1 to N). Then the next line starts with a positive integer M (≤200) followed by M Eva’s favorite color numbers given in her favorite order. Finally the third line starts with a positive integer L (≤104 ) which is the length of the given stripe, followed by L colors on the stripe. All the numbers in a line a separated by a space.

Output Specification:
For each test case, simply print in a line the maximum length of Eva’s favorite stripe.

Sample Input:
6
5 2 3 1 5 6
12 2 2 4 1 5 5 6 3 1 1 5 6

      
    
Sample Output:
7

2 解析

2.1 题意

给出喜欢的颜色顺序以及颜色条纹,要求去除颜色条纹中不喜欢的颜色形成新的序列,求新序列中按照颜色序列顺序最大序列长度

2.2 思路

2.2.1 思路一

  • 1 用一个int数值hashTable[i],将所有元素元素映射为-1,将输入的喜欢的颜色顺序依次映射为递增序列0,1,2…
  • 2 对于输入的颜色条纹i,去除掉i映射-1的颜色,把喜欢的颜色i映射为hashTable中存储的数字序列,形成新序列
  • 3 按最大不下降子序列进行求解

2.2.2 思路二

经典LCS模型(最长公共子序列)的两个序列的元素匹配必须一一对应的,但本题中允许公共部分产生重复元素,因此需要对模型进行修改。
计算dp[i][j]时,当A[i]不等于B[i]时,由于可以产生重复元素dp[i-1][j],dp[i][j-1]都会对dp[i][j]产生影响(dp[i-1][j-1]会通过dp[i-1][j]、dp[i][j-1]来影响dp[i][j], 因此不用考虑),而当A[i]等于B[i]时,dp[i][j]应该是dp[i-1][j],dp[i][j-1]较大值加1.

因此状态转移方程为:
d p [ i ] [ j ] = { m a x { d p [ i 1 ] [ j ] , d p [ i ] [ j 1 ] } + 1 , A [ i ] = B [ i ] m a x { d p [ i 1 ] [ j ] , d p [ i ] [ j 1 ] } , A [ i ] ! = B [ i ] dp[i][j]=\left\{ \begin{aligned} max\{dp[i-1][j],dp[i][j-1]\}+1,A[i] = B[i] \\ max\{dp[i-1][j],dp[i][j-1]\},A[i] != B[i] \\ \end{aligned} \right.
边界为:
边界:dp[i][0] = dp[0][j] = 0(0<= i <= n, 0 <= j <=m)

3 参考代码

3.1 思路一

#include <cstdio>
#include <algorithm>

using std::fill;
using std::max;

const int MAXN = 10010;
int stripe[MAXN];//去除掉不喜欢颜色的序列
int hashTable[MAXN];//将喜欢的颜色映射为递增序列
int dp[MAXN];//状态数组

int main(int argc, char const *argv[])
{
    int n, m, l;
    scanf("%d", &n);
    fill(hashTable, hashTable + n + 1, -1);
    scanf("%d", &m);

    int color;
    for (int i = 0; i < m; ++i)
    {
        scanf("%d", &color);
        hashTable[color] = i;
    }

    scanf("%d", &l);
    int count = 0;//统计新行程序列的个数
    for (int i = 0; i < l; ++i)
    {
        scanf("%d", &color);
        if(hashTable[color] != -1){
            stripe[count++] = hashTable[color];
        }
    }

    int ans = -1;
    for (int i = 0; i < count; ++i)
    {
        dp[i] = 1;
        for (int j = 0; j < i; ++j)
        {
            if(stripe[j] <= stripe[i] && (dp[j] + 1 > dp[i])){
                dp[i] = dp[j] + 1;
            }
        }
        ans = max(ans, dp[i]);
    }

    printf("%d\n", ans);
    return 0;
}

3.2 思路二

#include <cstdio>
#include <algorithm>

using std::max;

const int MAXA = 210;
const int MAXB = 10010;
int A[MAXA]; 
int B[MAXB];
int dp[MAXA][MAXB];

int main(int argc, char const *argv[])
{
    int n, m, l;
    scanf("%d", &n);
    
    scanf("%d", &m);
    for (int i = 1; i <= m; ++i)
    {
        scanf("%d", &A[i]);
    }
    
    scanf("%d", &l);
    for (int i = 1; i <= l; ++i)
    {
        scanf("%d", &B[i]);
    }

    //边界
    for (int i = 0; i <= m; ++i)
    {
        dp[i][0] = 0;
    }
    for (int j = 0; j <= l; ++j)
    {
        dp[0][j] = 0;
    }

    //状态转移方程
    for (int i = 1; i <= m; ++i)
    {
        for (int j = 1; j <= l; ++j)
        {
            if(A[i] == B[j]){
                dp[i][j] = max(dp[i-1][j], dp[i][j-1]) + 1;
            }else{
                dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
            }
        }
    }

    printf("%d\n", dp[m][l]);
    return 0;
}
发布了378 篇原创文章 · 获赞 52 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/qq_33375598/article/details/104450777
今日推荐