算法提高之拦截导弹
-
核心思想:线性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; }