最长上升子序列

最长公共子序列

题目描述
image
image

参考题解

记录第一个数组每个值的索引,然后将第二个数组转换为索引数组,求索引数组的最长上升子序列

#include <iostream>
#include <algorithm>

using namespace std;

const int N = 1e6+5, INF = 0x3f3f3f3f;

int id[N];//value to idx

int q[N];

int main()
{
    int n;
    cin >> n;
    for(int i = 1; i <= n; ++ i)
    {
        int tp;
        scanf("%d", &tp);
        id[tp] = i;
    }
    //寻找严格小于x的最大的数
    int tt = 0;
    q[0] = -INF; //哨兵
    for(int i = 0; i < n; ++ i)
    {
        int x;
        scanf("%d", &x);
        int k = id[x];
        if(k == 0)  continue;
        int l = 0, r = tt;
        while(l < r)
        {
            int mid = l+r+1>>1;
            if(q[mid] < k)  l = mid; //注意这里用k
            else    r = mid-1;
        }
        q[l+1] = k;
        tt = max(tt, l+1);
    }
    cout << tt << endl;
    return 0;
}

序列最大收益

题目描述
image
image

参考题解

最长上升子序列模型

#include <iostream>
#include <cstdio>

using namespace std;

const int N = 205;

int n, m, k;

int a[N];
int w[N][N];

int dp[N][N]; //dp[i][j]: 以a[i]结尾,删除了j个元素的情况下的选了a[i]的最小值

int main()
{
    cin >> n >> k >> m;
    for(int i = 1; i <= m; ++ i)
    {
        scanf("%d", a+i);
    }
    for(int i = 1; i <= n; ++ i)
        for(int j = 1; j <= n; ++ j)
        {
            scanf("%d", &w[i][j]);
        }
    int ans = 0;
    for(int i = 1; i <= m; ++ i) //选前i个元素, 并且要选a[i]
    {
        for(int j = 0; j < i; ++ j) //删除了j个元素
        {
            if(j > k)   continue;
            //求dp[i][j]
            if(i == 1)
            {
                dp[i][j] = 0;
            }
            for(int tk = 1; tk < i; ++ tk)
            {
                int dcnt = j - (i-tk-1);
                if(dcnt < 0)    continue;
                dp[i][j] = max(dp[i][j], dp[tk][dcnt]+w[a[tk]][a[i]]);
            }
            ans = max(ans, dp[i][j]);
        }
    }
    cout << ans << endl;
    return 0;
}
posted @ 2021-05-13 14:33  chaosliang  阅读(42)  评论(0)    收藏  举报