算法提高之拦截导弹

算法提高之拦截导弹

  • 核心思想:线性dp+贪心

    • 用数组存每一个下降子序列的最后一个数
    • 同时找出比当前数大的数中最小的一个(满足二分性质)
    • 存入该子序列(更新数组值)
  •   #include <iostream>
      #include <cstring>
      #include <algorithm>
      
      using namespace std;
      const int N = 1010, INF = 30010;
      
      int f[N],w[N];
      int q[N],cnt;
      int n,x;
      
      int main()
      {
          while(cin>>x) w[n++] = x;
          int res=0;
          for(int i=0;i<n;i++)  //dp
          {
              f[i]=1;
              for(int j=0;j<i;j++)
                  if(w[i] <= w[j]) f[i] = max(f[i],f[j]+1);
              res = max(res, f[i]);
          }
          cout<<res<<endl;  
          
          for(int i=0;i<n;i++)  //遍历每个数
          {
              int l=0,r=cnt;  //二分 cnt为子序列个数
              while(l<r)
              {
                  int mid = l+r>>1;
                  if(q[mid] >= w[i]) r = mid;  //如果w[i]可以放在mid上 则右侧所有的也可以放
                  //但是q为单调不下降数组 右边的一定>=mid 不会是更优解
                  else l = mid+1;
              }
              if(q[r] < w[i]) r++;  //找不到可以放的位置 再开一个
              cnt = max(cnt,r);  //主要看r是否更新 r更新则cnt更新
              q[r] = w[i];  //放入当前位置
          }
          cout<<cnt<<endl;
      }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阳光男孩01

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值