1045 Favorite Color Stripe (最长不下降子序列 LIS)

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 (≤) 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(≤) followed by M Eva‘s favorite color numbers given in her favorite order. Finally the third line starts with a positive integer L (≤) 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

  

一开始没审清题意,这里喜欢的颜色序列是可以不全部出现的,所以只有27/30分:

#include<cstdio>
#include<algorithm>
using namespace std;
struct node{
    int index=1;
    int data=1;
}c[10010];
int a[220];
int b[10010];

int main(){
    int n,m,k;
    scanf("%d",&n);
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
        scanf("%d",&a[i]);
    scanf("%d",&k);
    for(int i=1;i<=k;i++)
        scanf("%d",&b[i]);
    int maxx=-1,data,index,i,temp;
    for(i=1;i<=k;i++){
        if(b[i]==a[1]){
            temp=i;
            break;
        }
    }
    for(i=temp+1;i<=k;i++){
        for(int j=temp;j<i;j++){
            index=c[j].index;
            data=c[j].data;
            if(index==n){
                if(b[i]==a[index]&&(data+1>c[i].data)){
                    c[i].data=data+ 1;
                    c[i].index=index;
                }
            }else if(b[i]==a[index]){
                if(data+1>c[i].data){
                    c[i].data=data+1;
                    c[i].index=index;
                }
            }else if(b[i]==a[index+1]){
                if(data+1>c[i].data){
                    c[i].data=data+1;
                    c[i].index=index+1;
                }
            }
            if(c[i].data>maxx)
                maxx=c[i].data;
        }
    }
    printf("%d",maxx);
    return 0;
}

而且这种思路较为复杂,可以将喜欢的颜色通过hash按顺序映射到一个递增序列,即可方便转化为LIS问题:

#include<cstdio>
#include<algorithm>
using namespace std;
int dp[10010];
int b[10010];
int hash[220]={0};
int main(){
    int n,m,k,temp,now=1,now1=1,Max=-1;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        scanf("%d",&temp);
        hash[temp]=now++;
    }
    scanf("%d",&k);
    for(int i=1;i<=k;i++){
        scanf("%d",&temp);
        if(hash[temp]!=0){
            b[now1++]=temp;
        }
    }
    for(int i=1;i<now1;i++){
        dp[i]=1;
        for(int j=1;j<i;j++)
        if(hash[b[j]]<=hash[b[i]]&&dp[j]+1>dp[i]){
            dp[i]=dp[j]+1;
        }
        if(dp[i]>Max) Max=dp[i];
    }
    printf("%d",Max);
    return 0;
}

考虑使用LCS,这里的特殊点是公共部分可以存在重复元素,故对原模型进行修改

得出递推式

dp[i][j]=max(dp[i][j-1],dp[i-1][j])+1            如果a[i]等于b[j]的话

dp[i][j]=max(dp[i][j-1],dp[i-1][j])                  a[i]!=b[j]的话

#include<cstdio>
#include<algorithm>
using namespace std;
int a[220];
int b[10010];
int dp[220][10010];

int main(){
    int n,lenA,lenB,temp;
    scanf("%d%d",&n,&lenA);
    for(int i=1;i<=lenA;i++)
        scanf("%d",&a[i]);
    scanf("%d",&lenB);
    for(int i=1;i<=lenB;i++)
        scanf("%d",&b[i]);
    for(int i=0;i<=lenA;i++)
        dp[i][0]=0;
    for(int j=0;j<=lenB;j++)
        dp[0][j]=0;
    for(int i=1;i<=lenA;i++){
        for(int j=1;j<=lenB;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",dp[lenA][lenB]);
    return 0;
}


原文地址:https://www.cnblogs.com/exciting/p/10438330.html

时间: 2024-08-01 03:56:07

1045 Favorite Color Stripe (最长不下降子序列 LIS)的相关文章

SPOJ 3943 - Nested Dolls 最长不下降子序列LIS(二分写法)

现在n(<=20000)个俄罗斯套娃,每个都有宽度wi和高度hi(均小于10000),要求w1<w2并且h1<h2的时候才可以合并,问最少能剩几个. [LIS]乍一看跟[这题]类似,但是仔细看是有区别的,其实就相当于上一题多次求LIS,每次求完LIS后把得到的序列删去,然后重新求LIS,最后输出求LIS的次数,我一开始这样写,果然就TLE了.还是要另辟蹊径. 首先用贪心思想,先按照wi从大到小排序,wi相等的情况下hi从小到大,然后求最长不下降子序列(注意可以等于).输出其长度即可. 想

最长不下降子序列--LIS

#include <iostream> #include <vector> #include <algorithm> using namespace std; const int maxn = 100; int main() { int n; cin >> n; vector<int> datas; while (n--) { int tem; cin >> tem; datas.push_back(tem); } int dp[ma

PAT 1045. Favorite Color Stripe (30)

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

P2766 最长不下降子序列问题

\(\color{#0066ff}{题目描述}\) ?问题描述: 给定正整数序列x1,...,xn . (1)计算其最长不下降子序列的长度s. (2)计算从给定的序列中最多可取出多少个长度为s的不下降子序列. (3)如果允许在取出的序列中多次使用x1和xn,则从给定序列中最多可取出多少个长度为s的不下降子序列. ?编程任务: 设计有效算法完成(1)(2)(3)提出的计算任务. \(\color{#0066ff}{输入格式}\) 第1 行有1个正整数n,表示给定序列的长度.接下来的1 行有n个正整

swust oj 585--倒金字塔(LIS最长不下降子序列)

题目链接:http://acm.swust.edu.cn/problem/585/ Time limit(ms): 3000 Memory limit(kb): 65535 SWUST国的一支科学考察队到达了举世闻名的古埃及金字塔. 关于金字塔的建造一直是一个未解之谜, 有着“西方史学之父”之称的希罗多德认为,金字塔的建造是人力和牲畜,花费20 年时间从西奈半岛挖掘天然的石头运送到埃及堆砌而成.也有不少人认为是外星人修建的.人们发现胡夫金字塔的经线把地球分成东.西两个半球,它们的陆地面积是相等的

最长不下降子序列nlogn算法详解

今天花了很长时间终于弄懂了这个算法……毕竟找一个好的讲解真的太难了,所以励志我要自己写一个好的讲解QAQ 这篇文章是在懂了这个问题n^2解决方案的基础上学习. 解决的问题:给定一个序列,求最长不下降子序列的长度(nlogn的算法没法求出具体的序列是什么) 定义:a[1..n]为原始序列,d[k]表示长度为k的不下降子序列末尾元素的最小值,len表示当前已知的最长子序列的长度. 初始化:d[1]=a[1]; len=1; (0个元素的时候特判一下) 现在我们已知最长的不下降子序列长度为1,末尾元素

tyvj 1049 最长不下降子序列 n^2/nlogn

P1049 最长不下降子序列 时间: 1000ms / 空间: 131072KiB / Java类名: Main 描述 求最长不下降子序列的长度 输入格式 第一行为n,表示n个数第二行n个数 输出格式 最长不下降子序列的长度 测试样例1 输入 3 1 2 3 输出 3 备注 N小于5000for each num <=maxint 题意:中文题意 题解:不下降也就是>= n^n  dp[i] 表示前i个数的最长不下降子序列的长度 1 /*****************************

hdu 1160 FatMouse&#39;s Speed(最长不下降子序列+输出路径)

题意: FatMouse believes that the fatter a mouse is, the faster it runs. To disprove this, you want to take the data on a collection of mice and put as large a subset of this data as possible into a sequence so that the weights are increasing, but the s

【DP】最长不下降子序列问题(二分)

Description 给你一个长度为n的整数序列,按从左往右的顺序选择尽量多的数字并且满足这些数字不下降. Thinking 朴素dp算法:F[i]表示到第i位为止的最长不下降子序列长度 F[i]=max(F[j])+1,其中(j<i且a[j]<=a[i]) 时间复杂度:O(n2) 考虑维护一个队列g,用g[i]表示长度为i的最长不下降子序列结尾的最小值.根据g[i]的单调性,可以用二分查找的方法快速找到以当前数a[i]结尾的最长不下降子序列. Code 1 #include<cstd