• 10.导弹拦截


    [NOIP1999 普及组] 导弹拦截 - 洛谷

    导弹拦截3_哔哩哔哩_bilibili 


    解题思路:

    1.输入的若干个整数为导弹依次发射的高度,因为系统拦截导弹的高度是依次递减的,所要求的数量本质上是在问有多少个递减的高度,如果倒过来就是求最长上升子序列的问题(注意,相邻的两个数字相等也可以,因为是不上升子序列)

    2.求最长上升子序列的解法有朴素解法O(N^2)和贪心二分策略解法O(N*logN),在本专栏第九题,在此不再赘述。

    3.接下来看第二问,问至少需要多少个系统能拦截所有的导弹,受制于第一问的影响,很容易得出求出一个最长不上升子序列然后标记已被导弹拦截,然后求剩下的导弹的最长不上升子序列,但是这种做法是错误的!

    举个例子:7  5  4  1  6  3  2,这七个导弹中,第一轮扫掉了7 5 4 3 2,第二轮扫1,第三轮扫6,需要三个系统,但是7 5 4 1 可以用一个系统,6 3 2也同样用一个系统即可,答案为2

    所以这里不能用动态规划,应该用贪心的策略来解

    4.可以设置一个ans数组,来标记每个系统拦截完导弹后高度,后续的导弹在已有的系统中寻找,如果没有满足的系统,则需要再开辟一个系统,如果有的话,应该选取哪一个呢?应该选取差值最小的,这样,别的系统可以空出更多的空间来容纳高度更高一点的!

    举个例子:第一个系统的目前导弹拦截高度为158  第二个为155,现在飞来的导弹高度为65,则应该用第二个拦截,这样后续飞来157高度的就可以利用第一个系统拦截,不然的话,就得又开辟一个系统!

    5.最后输出ans数组的有效长度即可,为系统的个数


    代码实现:O(N^2) 


    1. #include
    2. using namespace std;
    3. int a[2010],dp[2010],ans[2010];
    4. int main()
    5. {
    6. int n,num=0;
    7. while(cin>>n)
    8. {
    9. a[++num]=n;
    10. }//输入数据
    11. for(int i=1;i<=num/2;i++)
    12. {
    13. swap(a[i],a[num-i+1]);
    14. }//头尾交换,便于求解上升子序列
    15. for(int i=1;i<=num;i++)
    16. dp[i]=1;//初始化为1,因为本身都是一个单调递增的序列
    17. for(int i=2;i<=num;i++)//从第二项开始遍历
    18. {
    19. for(int j=1;j//枚举第i项前面的数字
    20. {
    21. if(a[i]>=a[j])//如果可以以i结尾
    22. {
    23. dp[i]=max(dp[i],dp[j]+1);//状态转移方程
    24. }
    25. }
    26. }
    27. int max=0;
    28. for(int i=1;i<=num;i++)//遍历以每一个数字结尾的上升子序列数
    29. if(dp[i]>max)
    30. max=dp[i];//求最大值
    31. cout<
    32. int len=1;
    33. for(int i=1;i<=num/2;i++)
    34. {
    35. swap(a[i],a[num-i+1]);
    36. }//头尾交换,便于求解系统的个数
    37. ans[1]=a[1];//初始化第一个被拦截的导弹高度
    38. for(int i=2;i<=num;i++)//从第二个导弹的高度开始判断
    39. {
    40. bool flag=0;
    41. int min=99999999,res;
    42. for(int j=1;j<=len;j++)//在已有的系统中进行寻找
    43. {
    44. if(a[i]<=ans[j])//如果有这个系统可以拦截这枚导弹
    45. {
    46. flag=1;//打标记
    47. if((ans[j]-a[i])//找差值最小的编号
    48. {
    49. min=(ans[j]-a[i]);
    50. res=j;//记录该系统的编号
    51. }
    52. }
    53. }
    54. if(flag==1)//如果可以拦截这枚导弹
    55. ans[res]=a[i];//将这枚导弹放在离他高度最近的那个系统上
    56. else//如果拦截不了
    57. ans[++len]=a[i];//开辟一个新的系统,当前高度为a[i]
    58. }
    59. cout<//长度即为系统的数量
    60. return 0;
    61. }

    代码实现:O(N*logN)


    1. #include
    2. using namespace std;
    3. int a[100010],dp[100010],ans[100010];
    4. int main()
    5. {
    6. int n,num=0;
    7. while(cin>>n)
    8. {
    9. a[++num]=n;
    10. }//输入数据
    11. for(int i=1;i<=num/2;i++)
    12. {
    13. swap(a[i],a[num-i+1]);
    14. }//头尾交换,便于求解上升子序列
    15. int len=1;
    16. dp[1]=a[1];//将第一个数字设置为上升长度1
    17. for(int i=2;i<=num;i++)//从第二项开始遍历
    18. {
    19. if(a[i]>=dp[len])//如果当前项大于等于此时的上升序列最后一个数
    20. dp[++len]=a[i]; //长度加1,表示又多了一个
    21. else
    22. {
    23. int high=len,low=0,mid;//否则设置二分查找的区间
    24. while(low
    25. {
    26. mid=(low+high)/2;
    27. if(dp[mid]>a[i])
    28. high=mid;
    29. else
    30. low=mid+1;
    31. }
    32. dp[low]=min(dp[low],a[i]);//更新末尾数字
    33. }
    34. }
    35. cout<
    36. len=1;
    37. for(int i=1;i<=num/2;i++)
    38. {
    39. swap(a[i],a[num-i+1]);
    40. }//头尾交换,便于求解系统的个数
    41. ans[1]=a[1];//初始化第一个被拦截的导弹高度
    42. for(int i=2;i<=num;i++)//从第二个导弹的高度开始判断
    43. {
    44. bool flag=0;
    45. int min=99999999,res;
    46. for(int j=1;j<=len;j++)//在已有的系统中进行寻找
    47. {
    48. if(a[i]<=ans[j])//如果有这个系统可以拦截这枚导弹
    49. {
    50. flag=1;//打标记
    51. if((ans[j]-a[i])//找差值最小的编号
    52. {
    53. min=(ans[j]-a[i]);
    54. res=j;//记录该系统的编号
    55. }
    56. }
    57. }
    58. if(flag==1)//如果可以拦截这枚导弹
    59. ans[res]=a[i];//将这枚导弹放在离他高度最近的那个系统上
    60. else//如果拦截不了
    61. ans[++len]=a[i];//开辟一个新的系统,当前高度为a[i]
    62. }
    63. cout<//长度即为系统的数量
    64. return 0;
    65. }

  • 相关阅读:
    计算机毕业设计ssm+vue基本微信小程序的拼车自助服务小程序
    java jedis连接redis数据库实战
    代码随想录算法训练营day39
    学科知识图谱学习平台项目 :技术栈Java、Neo4j、MySQL等超详细教学
    Python Opencv实践 - 矩形轮廓绘制(直边矩形,最小外接矩形)
    nginx配置获取客户端的真实ip
    JDBC-03:PreparedStatement如何实现对数据库的增删改查操作
    如何在IDEA中创建Module、以及怎样在IDEA中删除Module?
    eMMC编程基础 -(二)eMMC基础介绍
    GitHub SSH 快速配置
  • 原文地址:https://blog.csdn.net/weixin_60869516/article/details/126654179