AcWing 272.LCIS的优化问题

朴素LCIS的时间为O(n^3),优化以后实现了边走边算的过程,实际上是因为满足所有局部最优的情况下的全局最优,优化一维度实现了O(n^2)

//朴素LCIS O(n^3)
#include <bits/stdc++.h>

using namespace std;

#define ll long long
#define PII pair<int, int>
#define PLL pair<ll, ll>

const int N = 3010;
const int M = 2 * N;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double PI = acos(-1.0);
const double eps = 1e-8;

int a[N], b[N];
int f[N][N];

//表示意义:所有由第一个序列的前i个字母,到第二个序列b[j]的公共上升子序列,该集合属性表示max
//那么可以讲f[i][j]看作两部分,一部分包含a[i],另一部分不包含a[i] -> f[i - 1][j](a[i] == b[j])
//对于包含a[i]的地方,我们对其进行最长上升子序列处理,盯准最后这个条件,看倒数第二个位置,去以b1,b2,·····bj结尾的序列max值
//遍历所有的,看看哪个最大
void solve()
{
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++)     cin >> a[i];
    for (int j = 1; j <= n; j++)     cin >> b[j];

    for(int i = 1; i <= n; i ++)
    {
        for(int j = 1; j <= n; j ++)
        {
            f[i][j] = f[i - 1][j];
            if(a[i] == b[j])//满足公共
            {
                f[i][j] = max(f[i][j],1);
                for(int k = 1;  k < j; k ++)
                {
                    if(b[k] < b[j])
                    {
                        f[i][j] = max(f[i][j],f[i][k] + 1);
                    }
                }
            }
        }
    }
    int maxx = 0;
    for (int i = 1; i <= n; i ++ )
    {
        maxx = max(maxx, f[n][i]);
    }
    cout << maxx << endl;
}
int main()
{
    
    solve();

    system("pause");
    return 0;
}

换个角度来看,可以理解为把公共和上升分开来求,

//优化LCIS O(n^2)
#include <bits/stdc++.h>

using namespace std;

#define ll long long
#define PII pair<int, int>
#define PLL pair<ll, ll>

const int N = 3010;
const int M = 2 * N;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double PI = acos(-1.0);
const double eps = 1e-8;

int a[N],b[N];
int f[N][N];

//表示意义:所有由第一个序列的前i个字母,到第二个序列b[j]的公共上升子序列,该集合属性表示max
//那么可以讲f[i][j]看作两部分,一部分包含a[i],另一部分不包含a[i] -> f[i - 1][j](a[i] == b[j])
//对于包含a[i]的地方,我们对其进行最长上升子序列处理,盯准最后这个条件,看倒数第二个位置,去以b1,b2,·····bj结尾的序列max值
//遍历所有的,看看哪个最大

void solve()
{
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++)     cin >> a[i];
    for (int j = 1; j <= n; j++)     cin >> b[j];

    for(int i = 1; i <= n; i ++)
    {
        int maxx = 1;
        for(int j = 1; j <= n; j ++)
        {
            f[i][j] = f[i - 1][j];
            if(a[i] == b[j])//满足公共
                f[i][j] = max(f[i][j],maxx);
            if(b[j] < a[i])//原来的b[k]<b[j],满足上升
                maxx = max(maxx,f[i][j] + 1);//保存局部最优解,前缀最大值
        }
    }
    int m = 0;
    for(int i = 1; i <= n; i ++) m = max(m,f[n][i]);
    cout << m << endl;
}
int main()
{
    
    solve();

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值