1044_拦截导弹

来源:互联网 发布:it便利店 编辑:程序博客网 时间:2024/06/03 19:37
/*Name: Copyright: 1044_拦截导弹Author: Date: 08-08-17 14:50Description: 1044_拦截导弹  1999年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解题目描述 Description某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。输入描述 Input Description输入导弹依次飞来的高度(雷达给出的高度数据是不大于30000的正整数)输出描述 Output Description输出这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。样例输入 Sample Input389 207 155 300 299 170 158 65 样例输出 Sample Output6(最多拦截导弹数)2(要拦截所有导弹最少要配备的系统数)数据范围及提示 Data Size & Hint导弹的高度<=30000,导弹个数<=20分析:第一问很简单,就是求最长不上升子序列,可以用高效的二分插入法。对于第二问用贪心的方法来做,*/#include <iostream>using namespace std;const int MAX = 20; int A[MAX];int S[MAX]; //记录到元素i为止的最长上升子序列的长度 int H[MAX]; //记录第k套系统的最小拦截高度 void DP(int n); //顺序查找 int main() {int n = 0;while (cin >> A[n]){n++;}DP(n);    return 0;}void DP(int n) //顺序查找 {int ans1 = 1, ans2 = 0, k = 0;  for (int i=0; i<n; i++){S[i] = 1; //默认到元素i为止的最长上升子序列的长度为1 for (int j=i-1; j>=0; j--)//逆序查找不大于A[i],且最长的元素,找到后更新S[i]和m的值{if (A[i] <= A[j] && S[j] >= S[i]){S[i] = S[j] + 1;if (S[i] > ans1) ans1 = S[i];}}//贪心法求系统数量,每次都用拦截高度最小的那套来拦截,若超出已有系统的最小高度,则增加一套新的系统for (k=0; k<ans2; k++)//ans2表示目前系统的总数量,H[k]表示第k套系统,k越小,该系统的最小拦截高度越低 {if (H[k] >= A[i])break;}if (k < ans2)//更新第k套系统的最小拦截高度 H[k] = A[i];else //若超出已有系统的最小高度,则增加一套新的系统,初始化其最小拦截高度为A[i] H[ans2++] = A[i];}cout << ans1 << endl << ans2 << endl ;}

/*Name: Copyright: 1044_拦截导弹Author: Date: 08-08-17 14:50Description: 1044_拦截导弹  1999年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解题目描述 Description某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。输入描述 Input Description输入导弹依次飞来的高度(雷达给出的高度数据是不大于30000的正整数)输出描述 Output Description输出这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。样例输入 Sample Input389 207 155 300 299 170 158 65 样例输出 Sample Output6(最多拦截导弹数)2(要拦截所有导弹最少要配备的系统数)数据范围及提示 Data Size & Hint导弹的高度<=30000,导弹个数<=20分析:第一问很简单,就是求最长不上升子序列,可以用高效的二分插入法。对于第二问用贪心的方法来做,*/#include <iostream>using namespace std;const int MAX = 20; int A[MAX];int S[MAX]; //记录到元素i为止的最长上升子序列的长度 int H[MAX]; //记录第k套系统的最小拦截高度 void DP(int n); //顺序查找 int main() {int n = 0;while (cin >> A[n]){n++;}DP(n);    return 0;}void DP(int n) //顺序查找 {int ans1 = 1, ans2 = 1;for (int i=0; i<n; i++){S[i] = H[i] = 1;for (int j=i-1; j>=0; j--){if (A[i] <= A[j]){S[i] = max(S[i], S[j]+1);ans1 = max(ans1, S[i]);}else{H[i] = max(H[i], H[j]+1);ans2 = max(ans2, H[i]);}}}cout << ans1 << endl << ans2 << endl ;}

原创粉丝点击