最长上升子序列
假定dp [k]表示以x[k]做为“终点”的最长上升子序列的长度,那么:
dp [1] = 1
dp [k] = max { dp [i] :1<i < k 且 x[i] < x[k]且 k≠1 } + 1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | //len表示字符串长度,x[]表示字符串数组,dp[i]表示从1到i位置最长上升子序列长度 int dp(int len,int x[],int dp[]){ int ans = 1; int maxx = 0; dp[1] = 1; for(int i = 2 ; i <= len ; i ++){ maxx = 0; for(int j = 1 ; j < i ; j ++) if(dp[j] > maxx && x[j] < x[i]) maxx = dp[j]; dp[i] = maxx+1; ans = max(dp[i],ans); } return ans; } |
最长下降子序列
假定dp [k]表示以x[k]做为“终点”的最长下降子序列的长度,那么:
dp [1] = 1
dp [k] = max { dp [i] :1<i < k 且 x[i] > x[k]且 k≠1 } + 1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | //len表示字符串长度,x[]表示字符串数组,dp[i]表示从1到i位置最长下降子序列长度 int dp(int len,int x[],int dp[]){ int ans = 1; int maxx = 0; dp[1] = 1; for(int i = 2 ; i <= len ; i ++){ maxx = 0; for(int j = 1 ; j < i ; j ++) if(dp[j] > maxx && x[j] > x[i]) maxx = dp[j]; dp[i] = maxx+1; ans = max(dp[i],ans); } return ans; } |
例题:
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
Input Description
输入导弹依次飞来的高度(雷达给出的高度数据是不大于30000的正整数)
Output Description
输出这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。
Sample Input
1 | 389 207 155 300 299 170 158 65 |
Sample Output
1 | 6 2 |
Data Size & Hint
导弹的高度<=30000,导弹个数<=20
题解:
题中第一问和第二问实际上分别是求序列的最长下降子序列和最长上升子序列。
下面以最长下降子序列为例,
状态转移方程为:dp1[i] = max(dp1[j]) + 1, j从1到i-1且a[j] > a[i]。
即从i之前(不包含i)的样例中找到满足下降条件(a[j]>a[i])的最大值,并加1。
最后,dp1数组中的最大值即为所求。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | #include <iostream> #include <algorithm> #include <cstdio> #include <cstring> #include <cmath> using namespace std; const int maxn = 100000+5; int n = 0; int dp1[maxn],dp2[maxn]; int x[maxn],dp[maxn]; //len表示字符串长度,x[]表示字符串数组,dp[i]表示从1到i位置最长上升子序列长度 int dp11(int len,int x[],int dp[]){ int ans = 1; int maxx = 0; dp1[1] = 1; for(int i = 2 ; i <= len ; i ++){ maxx = 0; for(int j = 1 ; j < i ; j ++) if(dp1[j] > maxx && x[j] > x[i]) maxx = dp1[j]; dp1[i] = maxx+1; ans = max(dp1[i],ans); } return ans; } //len表示字符串长度,x[]表示字符串数组,dp[i]表示从1到i位置最长下降子序列长度 int dp22(int len,int x[],int dp[]){ int ans = 1; int maxx = 0; dp2[1] = 1; for(int i = 2 ; i <= len ; i ++){ maxx = 0; for(int j = 1 ; j < i ; j ++) if(dp2[j] > maxx && x[j] < x[i]) maxx = dp2[j]; dp2[i] = maxx+1; ans = max(ans,dp2[i]); } return ans; } int main() { for(int i = 1 ; i <= 8 ; i ++){ cin >> x[i]; } cout << dp11(8,x,dp) << endl; cout << dp22(8,x,dp) << endl; return 0; } |