子序列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 }

浙公网安备 33010602011771号