dp----最长上升子序列问题


 最原始问题:

 1 给定一个长度为 N 的数列,求数值严格单调递增的子序列的长度最长是多少。
 2 
 3 输入格式
 4 第一行包含整数 N。
 5 
 6 第二行包含 N 个整数,表示完整序列。
 7 
 8 输出格式
 9 输出一个整数,表示最大长度。
10 
11 数据范围
12 1≤N≤100013 ?109≤数列中的数≤109
14 输入样例:
15 7
16 3 1 2 1 8 5 6
17 输出样例:
18 4

最原始解法:

 《变式----最长上升子序列+最长下降子序列》

1014. 登山

五一到了,ACM队组织大家去登山观光,队员们发现山上一共有N个景点,并且决定按照顺序来浏览这些景点,即每次所浏览景点的编号都要大于前一个浏览景点的编号。

同时队员们还有另一个登山习惯,就是不连续浏览海拔相同的两个景点,并且一旦开始下山,就不再向上走了。

队员们希望在满足上面条件的同时,尽可能多的浏览景点,你能帮他们找出最多可能浏览的景点数么?

输入格式
第一行包含整数N,表示景点数量。

第二行包含N个整数,表示每个景点的海拔。

输出格式
输出一个整数,表示最多能浏览的景点数。

数据范围
2≤N≤1000
输入样例:
8
186 186 150 200 160 130 197 220
输出样例:
4
题源:AcWing 1014. 登山

 代码:

 1 #include 
 2 #include 
 3 #include 
 4 using namespace std;
 5 const int N = 1010;
 6 int ldp[N], rdp[N], h[N];
 7 int main()
 8 {
 9     int n;
10     scanf("%d", &n);
11     for (int i = 1; i <= n; i++)
12     {
13         scanf("%d", &h[i]);
14     }
15     for (int i = 1; i <= n; i++)
16     {
17         ldp[i] = 1;
18         for (int j = 1; j < i; j++)
19         {
20             if (h[j] < h[i])
21             {
22                 ldp[i] = max(ldp[i], ldp[j] + 1);
23             }
24         }
25     }
26     for (int i=n;i>=1;i--)
27     {
28         for (int j=n;j>=i+1;j--)
29         {
30             if (h[i]>h[j])
31             {
32                 rdp[i]=max(rdp[i],rdp[j]+1);
33             }
34         }
35         ldp[i]+=rdp[i];
36     }
37     int ans = 0;
38     for (int i = 1; i <= n; i++)
39     {
40         ans = max(ldp[i], ans);
41     }
42     printf("%d", ans);
43     return 0;
44 }