子序列dp

acwing 895.最长上升子序列

https://www.acwing.com/problem/content/897/

 1 #include <iostream>
 2 #include <algorithm>
 3 
 4 using namespace std;
 5 
 6 const int N = 10100;
 7 int f[N],a[N];
 8 
 9 int main(){
10     int n ;
11     cin >> n;
12     for(int i = 1 ; i <= n ; i ++)cin >> a[i];
13     
14     for(int i = 1 ; i <= n ; i ++)
15     {
16         f[i] = 1;
17         for(int j = 1 ; j < i ; j ++)
18             if(a[i] > a[j])
19             f[i] = max(f[i], f[j] + 1);
20     }
21     
22     int res = 0;
23     for(int i = 1 ; i <= n ; i ++)res = max(res, f[i]);
24     cout << res << endl;
25     return 0;
26 }

 

acwing 1010.拦截导弹

https://www.acwing.com/activity/content/problem/content/1264/1/

题意:求最长的下降子序列的长度,求至少要几个下降子序列才可以完全覆盖所有的数。

第一问就是最长子序列问题。第二问采用贪心。

从前往后扫描每一个数,对于每一个数分两种情况:

①如果现有的子序列结尾都小于当前的数字,就重新开一个序列组。

②将当前数放到大于等于它的最小的数后面。

 1 #include <iostream>
 2 
 3 using namespace std;
 4 
 5 int f[10010], g[10010], a[10010];
 6 int res = 0;
 7 
 8 int main(){
 9     int n = 0;
10     while(cin >> a[n])n++;
11     for(int i = 0 ; i < n ; i ++)
12     {
13         f[i] = 1;
14         for(int j = 0 ; j < i ; j ++)
15             if(a[j] >= a[i])
16                 f[i] = max(f[i], f[j] + 1);
17         res = max(res, f[i]);
18     }
19     cout << res << endl;
20     
21     int cnt = 0;
22     for(int i = 0; i < n ; i ++)
23     {
24         int k = 0;
25         while(k < cnt && g[k] < a[i])k++;
26         g[k] = a[i];
27         if(k >= cnt)cnt++;
28     }
29     cout << cnt << endl;
30     return 0;
31 }

 

acwing 187.导弹防御系统

https://www.acwing.com/problem/content/189/

相比于拦截导弹,我们可以选择下降还是上升。所以在上一题的第二问的基础上,需要枚举是选择上升子序列还是下降子序列,所以要$dfs$枚举($dfs$求最小步数有两种方式:全局变量和迭代加深)。

 1 #include <iostream>
 2 #include <algorithm>
 3 
 4 using namespace std;
 5 
 6 const int N = 51;
 7 int down[N], up[N];
 8 int n, ans;
 9 int a[N];
10 
11 void dfs(int u, int su, int sd)
12 {
13     if(su + sd >= ans)return;
14     if(u == n)
15     {
16         ans = su + sd;
17         return;
18     }
19     
20     //上升
21     int k = 0;
22     while(k < su && up[k] >= a[u])k ++;
23     int t = up[k];
24     up[k] = a[u];
25     if(k < su)dfs(u + 1, su, sd);
26     else dfs(u + 1, su + 1, sd);
27     up[k] = t;
28     
29     //下降
30     k = 0;
31     while(k < sd && down[k] <= a[u])k ++;
32     t = down[k];
33     down[k] = a[u];
34     if(k < sd)dfs(u + 1, su, sd);
35     else dfs(u + 1, su, sd + 1);
36     down[k] = t;
37 }
38 
39 int main(){
40     while(cin >> n , n)
41     {
42         for(int i = 0 ; i < n ; i ++)cin >> a[i];
43         
44         ans = n;
45         dfs(0, 0, 0);
46         
47         cout << ans << endl;
48     }
49     return 0;
50 }

 

posted @ 2020-04-14 11:26  dzcixy  阅读(152)  评论(0)    收藏  举报