PAT甲级真题1045 最佳彩色带(两种DP)

伊娃试图用一条原始色带给自己制作一条喜欢的色带。

她会通过剪掉原始色带中多余的部分,将其余部分拼接起来,从而使得色带中只包含她喜欢的颜色,并且这些颜色按照她喜欢的顺序排列。

据说正常的人眼只能分辨不到 200 种不同的颜色,因此伊娃喜欢的颜色数量是有限的。

原始色带的长度可能会很长,她希望拼剪成的能够使她满意的色带也尽可能的长。

因此,她需要你来帮她确定能够拼剪出的,使得她满意的色带的最大可能长度。

注意,修剪方案可能并不唯一,例如给定颜色为 {2 2 4 1 5 5 6 3 1 1 5 6} 的色带,如果伊娃最喜欢的颜色以她最喜欢的顺序排列为 {2 3 1 5 6},则她有 4 种可能的最佳解决方案 {2 2 1 1 1 5 6},{2 2 1 5 5 5 6},{2 2 1 5 5 6 6},{2 2 3 1 1 5 6}。

拼剪而成的色带不一定要包含所有她喜欢的颜色,但是一定不能包含她不喜欢的颜色,并且包含的颜色之间的相对顺序应该与她喜欢的顺序保持一致。

输入格式
第一行包含整数 N,表示涉及到的颜色总数,颜色编号依次为 1∼N。

第二行首先包含一个整数 M,表示她喜欢的颜色数量,接下来会按照她喜欢的排列顺序,依次给出她喜欢的 M 种颜色的编号。

第三行首先包含一个整数 L,表示原始色带的长度,然后包含 L 个整数,表示原始色带的具体颜色分布。

输出格式
输出一个整数,表示她能够满意的色带的最大长度。

数据范围
1≤N≤200,
1≤M≤200,
1≤L≤104

输入样例:
6
5 2 3 1 5 6
12 2 2 4 1 5 5 6 3 1 1 5 6
输出样例:
7
#include<bits/stdc++.h>
using namespace std;
const int N=10010;
int a[N],b[210];
int dp[N];
int n,m,k;
int main(){
    cin>>n;
    cin>>m;
    for(int i=1;i<=m;i++)cin>>b[i];
    cin>>k;
    for(int i=1;i<=k;i++)scanf("%d",&a[i]);
    for(int i=1;i<=k;i++){
        bool flag=false;
        for(int j=1;j<=m;j++){
            if(a[i]==b[j]){
                a[i]=j;//赋予权值
                flag=true;
                break;
            }
        }
        if(flag==false)a[i]=10000;//不喜欢的颜色赋予最大值,不考虑
    }
    if(a[1]<=m)dp[1]=1;
    int maxv=dp[1];
    for(int i=2;i<=k;i++){
        if(a[i]<=m){//是合法颜色
        dp[i]=1;//合法颜色的长度最短为1,前面都是不合法的
           for(int j=1;j<i;j++){
               if(a[j]<=a[i]&&(dp[j]+1>dp[i])&&a[j]<=m){
                   dp[i]=dp[j]+1;
               }
           }
           maxv=max(maxv,dp[i]);
        }
    }
    cout<<maxv<<endl;
    return 0;
}
#include <iostream>

using namespace std;

const int N = 210, M = 10010;

int n, m, l;
int p[N], s[M];
int f[N][M];//f[i][j]表示p[1]到p[i]和s[1]到s[j]最大公共部分

int main()
{
    cin >> n;

    cin >> m;
    for (int i = 1; i <= m; i ++ ) cin >> p[i];

    cin >> l;
    for (int i = 1; i <= l; i ++ ) cin >> s[i];

    for (int i = 1; i <= m; i ++ )
        for (int j = 1; j <= l; j ++ )
        {
            f[i][j] = max(f[i - 1][j],f[i][j-1]);
     //f[i][j - 1]+1不能写成f[i - 1][j - 1]+1,因为比如3 5和3 5 5
            if (p[i] == s[j]) f[i][j] = max(f[i][j], f[i][j - 1] + 1);
        }

    cout << f[m][l] << endl;

    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小王子y

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值