怪盗基德的滑翔翼
数据范围
1≤K≤100,
1≤N≤100,
0<h<10000
输入样例:
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>
using namespace std;
const int N=110;
int f[N],a[N],g[N],n;
int main()
{
int T;
cin>>T;
while(T--)
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
int res=0;
for(int i=1;i<=n;i++)
{
f[i]=g[i]=1;
for(int j=1;j<=i;j++)
if(a[j]<a[i])
f[i]=max(f[i],f[j]+1);
else if(a[i]<a[j])
g[i]=max(g[i],g[j]+1);
res=max(res,f[i]);
res=max(res,g[i]);
}
cout<<res<<endl;
}
return 0;
}
登山

数据范围
2≤N≤1000
输入样例:
8
186 186 150 200 160 130 197 220
输出样例:
4
解法:求出以每个点为结尾的最大上升与下降子序列和的最大值,因此分别正逆求最大上升子序列,再逐点取最值即可
#include <iostream>
using namespace std;
const int N=1010;
int n,f[N],a[N],g[N];
int main()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
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);
}
for(int i=n;i;i--)
{
g[i]=1;
for(int j=n;j>i;j--)
if(a[j]<a[i])
g[i]=max(g[i],g[j]+1);
}
int res=0;
for(int i=1;i<=n;i++)
{
res=max(res,f[i]+g[i]-1); //这里注意要减一,因为当前点同时算在 f[i] g[i]中
}
cout<<res<<endl;
return 0;
}
合唱队形

数据范围
2≤N≤100,
130≤Ti≤230
输入样例:
8
186 186 150 200 160 130 197 220
输出样例:
4
解法:与上一题类似,求出最大上升与下降子序列和的最大值,再用总数减去即可
#include <iostream>
using namespace std;
const int N=110;
int f[N],g[N],a[N],n;
int main()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++)
{
f[i]=1;
for(int j=1;j<i;j++)
if(a[j]<a[i])
f[i]=max(f[i],f[j]+1);
}
for(int i=n;i;i--)
{
g[i]=1;
for(int j=n;j>i;j--)
if(a[j]<a[i])
g[i]=max(g[i],g[j]+1);
}
int res=0;
for(int i=1;i<=n;i++) res=max(res,f[i]+g[i]-1);
cout<<n-res<<endl;
return 0;
}
友好城市

数据范围
1≤N≤5000,
0≤xi≤10000
输入样例:
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;
typedef pair<int,int> PII; //直接用 pair 存储便于排序
int f[N],n;
PII a[N];
int main()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i].first>>a[i].second;
sort(a+1,a+1+n);
int res=0;
for(int i=1;i<=n;i++)
{
f[i]=1;
for(int j=1;j<i;j++)
if(a[j].second<a[i].second)
f[i]=max(f[i],f[j]+1);
res=max(f[i],res);
}
cout<<res<<endl;
return 0;
}
最大上升子序列和

数据范围
1≤N≤1000
输入样例:
7
1 7 3 5 9 4 8
输出样例:
18
解法:与求最大上升子序列相似
#include <iostream>
using namespace std;
const int N=1010;
int n,f[N],a[N];
int main()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
int res=0;
for(int i=1;i<=n;i++)
{
f[i]=a[i]; // f[i] 存储的是以第 i 个数结尾的最大上升子序列和,因此要初始化为 a[i]
for(int j=1;j<i;j++)
if(a[j]<a[i])
f[i]=max(f[i],f[j]+a[i]);
res=max(f[i],res);
}
cout<<res<<endl;
return 0;
}

2343

被折叠的 条评论
为什么被折叠?



