点击打开链接(新发现的一个oj,样式很小清新呀)
题目大意:n个导弹,(1)求最大非上升子序列长度(2)要拦截所有导弹最少要配备这种导弹拦截系统的套数
思路1:每一次求最大非上升子序列,求一次删一次。直到数组全0。有点害怕超时,然而没有hhh
注意:
1、需要记录序列不能用O(nlogn)的方法
2、lower_bound()函数的要求是查找数组是非递减的,找第一个>=x的位置;upper_bound(a.begin(),a.end(),x)求求非递减数组中第一个>x的位置
3、剔除元素后,内外循环都要判断a[i]==0
4、使用memset要加头文件
5、剔除元素判断必须用dp[j],用pre[j]最后一个元素剔除不了
思路2:(2)是求最大上升子序列(参考,虽然没很懂,但是记住这个定理吧,可以套模板)
两个定理:定理1 令(X,≤)是一个有限偏序集,并令r是其最大链的大小。则r为X的最大反链数。
对偶定理:对于一个偏序集,其最少反链划分数等于其最长链的长度。这就是Dilworth定理。
思路1代码:(思路2就不敲了。。。)
#include
#include
#include//第n+1次忘了这个。。。
using namespace std;
int a[1001],pre[1001],dp[1001]={0};
int main()
{
int i,k,M,Mindex,j,count,n=0;
cin>>k;
for (i=1;i<=k;i++)
cin>>a[i];
count=k;
while(count)//数组中非0个数
{
n++;
M=0;
memset(dp,0,sizeof(dp));
memset(pre,0,sizeof(dp));
for (i=k;i>=0;i--)
{
if (a[i]==0)continue;//忽略已删除元素
for (j=k;j>i;j--)
{
if (a[j]==0) continue;//不能忘记!!!!!里面也要判断一次
if ( a[j]<=a[i] && dp[j]>dp[i])
{
dp[i]=dp[j];
pre[i]=j;//记录序列
}
}
dp[i]++;
if (dp[i]>M)
{
M=dp[i];
Mindex=i;
}
}
if (count==k)//输出第一次求得的序列长
cout<