计蒜客 动态规划基础 蒜头跳木桩
题目:
蒜头君面前有一排 n 个木桩,木桩的高度分别是h1,h2,h3⋯hn。蒜头第一步可以跳到任意一个木桩,接下来的每一步蒜头不能往回跳只能往前跳,并且跳下一个木桩的高度 不大于 当前木桩。蒜头君希望能踩到尽量多的木桩,请你帮蒜头计算,最多能踩到多少个木桩。
输入格式
第一行输入一个整数 n 代表木桩个数。第二行输入 n 个整数h1,h2,h3⋯hn,分别代表 n 个木桩的高度。(1≤n≤1000,1≤hi≤100000)
输出格式
输出一个整数,代表最多能踩到的木桩个数,占一行。
样例输入
6
3 6 4 1 4 2
样例输出
4
思路
不难发现,这时一道 LIS (最长上升子序列)的题目。(当然,这里是最长不上升子序列,其实是一回事。)
O(n2) 复杂度的算法并不能满足全部的数据,所以使用 O(nlogn) 的算法。
O(nlogn) 算法的思路就是储存一个对应 dp 值的最小值,它们一定是升序的。例如标程中将其储存于 ans 数组中,这样,下次有新的最小数出现的时候,利用二分就可以最快找到放入的位置。程序中,变量 pos 是放入 a[i] 的位置,变量 len 就是最长的长度,即为答案。
标程
1 #include <iostream>
2 #include <cstdlib>
3 #include <cstdio>
4 #include <algorithm>
5 #include <cstring>
6 using namespace std;
7 int n,a[1000+5],dp[1000+5],ans[1000+5],len;
8 int binarySearch(int arr[], int first, int end, int tar)
9 {
10 while (end > first)
11 {
12 int mid = (first+end)/2;
13 if (arr[mid]<tar)
14 {
15 end = mid;
16 }
17 else
18 {
19 first = mid+1;
20 }
21 }
22 return end;
23 }
24 int main()
25 {
26 cin >> n;
27 for (int i=1; i<=n; i++)
28 {
29 cin >> a[i];
30 }
31 ans[1] = a[1];
32 len = 1;
33 for (int i=2; i<=n; i++)
34 if (a[i] <= ans[len])
35 ans[++len] = a[i];
36 else
37 {
38 int pos = binarySearch(ans,1,len,a[i]);
39 ans[pos] = a[i];
40 }
41 cout << len << endl;
42 return 0;
43 } 相关推荐
yedaoxiaodi 2020-07-26
us0 2020-06-25
Eduenth 2020-06-22
Oudasheng 2020-06-13
sunjunior 2020-05-19
chenfei0 2020-04-30
老和山下的小学童 2020-04-20
SystemArchitect 2020-04-14
jiayuqicz 2020-02-02
zangdaiyang 2020-01-25
yuanran0 2020-01-20
yedaoxiaodi 2020-01-12
rein0 2020-01-01
Oudasheng 2019-12-27
Oudasheng 2019-12-22
wuxiaosi0 2019-12-17
trillionpower 2019-11-23
ustbfym 2019-11-03