最长上升序列模型
二、最长上升序列模型
怪盗基德的滑翔机

样例输入:
3
8
300 207 155 299 298 170 158 65
8
65 158 170 298 299 155 207 300
10
2 1 3 4 5 6 7 8 9 10
样例输出:
6
6
9
代码模板:
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 100010;
int n;
int a[N],f[N];
int main(){
int T;
cin>>T;
while(T--)
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
//正向求解LIS问题
int res=0;
for(int i=1;i<=n;i++)
{
f[i]=1;
for(int j=1;j<i;j++)
if(a[i]>a[j])
f[i]=max(f[i],f[j]+1);
res=max(res,f[i]);
}
//反向求解LIS问题
for(int i=n;i;i--)
{
f[i]=1;
for(int j=n;j>i;j--)
if(a[i]>a[j])
f[i]=max(f[i],f[j]+1);
res=max(f[i],res);
}
cout<<res<<endl;
}
}
登山

样例输入:
8
186 186 150 200 160 130 197 220
样例输出:
4
代码模板:
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 1010;
int f[N],g[N];
int w[N];
int main()
{
int n;
cin>>n;
int res =0;
for(int i=1;i<=n;i++)
{
cin>>w[i];
}
for(int i=1;i<=n;i++)
{
f[i]=1;
for(int j=1;j<i;j++)
{
if(w[i]>w[j])
f[i]=max(f[i],f[j]+1);
}
}
for(int i=n;i>=1;i--)
{
g[i]=1;
for(int j=n;j>i;j--)
{
if(w[i]>w[j])
g[i]=max(g[i],g[j]+1);
}
}
for(int i=1;i<=n;i++)
res=max(res,f[i]+g[i]-1);
cout<<res<<endl;
return 0;
}
友好城市

思路:
样例输入:
7
22 4
2 6
10 3
15 12
9 8
17 17
4 2
样例输出:
4
代码模板:
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 5010;
pair<int, int> a[N];
int n, f[N], res;
int main()
{
cin >> n;
for ( int i = 0; i < n; i ++ ) cin >> a[i].first >> a[i].second;
sort(a, a + n);
for ( int i = 0; i < n; i ++ )
{
f[i] = 1;
for ( int j = 0; j < i; j ++ )
if ( a[i].second > a[j].second )
f[i] = max(f[i], f[j] + 1);
res = max(res, f[i]);
}
cout << res;
return 0;
}
导弹拦截

样例输入:
389 207 155 300 299 170 158 65
样例输出:
6
2
样例模板:
#include <sstream>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1010;
int n;
int h[N], f[N], q[N];
int main()
{
string line;
getline(cin, line);
stringstream ssin(line);
while (ssin >> h[n]) n ++ ;
int res = 0, cnt = 0;
for (int i = 0; i < n; i ++ )
{
f[i] = 1;
for (int j = 0; j < i; j ++ )
if (h[i] <= h[j])
f[i] = max(f[i], f[j] + 1);
res = max(res, f[i]);
int k = 0;
while (k < cnt && q[k] < h[i]) k ++ ;
if (k == cnt) q[cnt ++ ] = h[i];
else q[k] = h[i];
}
printf("%d\n", res);
printf("%d\n", cnt);
return 0;
}
导弹防御系统

样例输入:
5
3 5 2 4 1
0
样例输出:
2
代码模板:
//暴搜
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 55;
int n;
int q[N];
int up[N], down[N];
int ans;
void dfs(int u, int su, int sd) {
if (su + sd >= ans) return; // ans不可能再小了
if (u == n) {
ans = su + sd; // su, sd 分别表示 len(up[]), len(down[])
return;
}
// 情况1:将当前数放到上升子序列中
int k = 0;
while (k < su && up[k] >= q[u]) k ++;
int t = up[k];
up[k] = q[u];
if (k < su) dfs(u + 1, su, sd);
else dfs(u + 1, su + 1, sd);
up[k] = t;
// 情况2:将当前数放到下降子序列中。
k = 0;
while (k < sd && down[k] <= q[u]) k ++;
t = down[k];
down[k] = q[u];
if (k < sd) dfs(u + 1, su, sd);
else dfs(u + 1, su, sd + 1);
down[k] = t;
}
int main() {
while (cin >> n, n) {
for (int i = 0; i < n; i ++)
cin >> q[i];
ans = n;
dfs(0, 0, 0);
cout << ans << endl;
}
}
//迭代加深
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 60;
int n;
int h[N];
int up[N], down[N];
bool dfs(int depth, int u, int su, int sd) {
// depth 序列上限, su, sd, u 上一个数或者下一个数
if (su + sd > depth) return false; // 9 > 8, 深度从0开始
if (u == n) return true;
// 枚举所有选法
// 枚举上升子序列
bool flag = false;
for (int i = 1; i <= su; i ++) // 上升子序列
if (up[i] < h[u]) {
int t = up[i];
up[i] = h[u];
if (dfs(depth, u + 1, su, sd)) return true;
up[i] = t;
flag = true;
break;
}
if (!flag) {
up[su + 1] = h[u];
if (dfs(depth, u + 1, su + 1, sd)) return true;
}
// 枚举下降子序列
flag = false;
for (int i = 1; i <= sd; i ++)
if (down[i] > h[u]) {
int t = down[i];
down[i] = h[u];
if (dfs(depth, u + 1, su, sd)) return true;
down[i] = t;
flag = true;
break;
}
if (!flag) {
down[sd + 1] = h[u];
if (dfs(depth, u + 1, su, sd + 1)) return true;
}
return false;
}
int main() {
while (cin >> n, n) {
for (int i = 0; i < n; i ++) cin >> h[i];
int depth = 0;
while (!dfs(depth, 0, 0, 0)) depth ++;
cout << depth << endl;
}
return 0;
}
最长公共上升子序列

思路:

样例输入:
4
2 2 1 3
2 1 2 3
样例输入:
2
代码模板:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
const int N = 3005;
int n,f[N][N],a[N],b[N],st[N];
int main(){
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++) cin>>b[i];
// 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);
// }
// }
// }
//优化
for(int i=1;i<=n;i++)
{
int maxt=0;
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],maxt+1);
if(a[i]>b[j]) maxt=max(maxt,f[i-1][j]);
}
}
int res=0;
for(int i=1;i<=n;i++) res=max(res,f[n][i]);
cout<<res<<endl;
return 0;
}

浙公网安备 33010602011771号