最长上升子序列
最长公共子序列
参考题解
记录第一个数组每个值的索引,然后将第二个数组转换为索引数组,求索引数组的最长上升子序列
#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;
}
序列最大收益
参考题解
最长上升子序列模型
#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;
}





浙公网安备 33010602011771号