怎么办呢?多搞几套系统呗!你说说倒蛮容易,成本呢?成本是个大问题啊.所以俺就到这里来求救了,请帮助计算一下最少需要多少套拦截系统.
求最长(严格)上升序列(Longest Increasing Subsequence)。这样的长度才是 最少需要的 套数,因为这个序列中的任何两个导弹都不能共用一个拦截系统 ,而且其余的导弹 都能和这个最长序列中的某个导弹分为同一组。
证明:对于数列中的一个最长(严格)上升序列,长度为k,其余任何数都可以分在这个最长序列中,构成k组单调减序列:
例如 a1 a2 a3 a4 a5 a6 a7 a8 a9
已经求得 a3 a5 a6 a8 为最长严格上升子序列(LSIS),且组成4个组。
对于a9
a9 <= a8 ,否则a9属于这个LSIS;所以,a9可以和a8分一组。
对于a7
若a7 <= a6, 则a7可以和a6分一组;
若a7 > a6,
a. 如果a7 >= a8,则a7可以和a8分一组;
b. 如果a7 < a8, 则 a6 a7 a8 可替代a6 a8,构成LSIS,矛盾。
对于a4,同a7
对于a2,a2 >= a3,否则与LSIS矛盾。所以,a2与a3可分为一组。
对于a1,
若a1 >= a2 可与a3同组
若a1 < a2,
a.如果a1 >= a3,可以与a3分在一组
b.如果a1 < a3, 则 a1 a3 可代替a3,与LSIS,矛盾。
同理可证任意n,k。
#include<stdio.h>
#define N 30001
int ary[N], dp[N];
int LIS(int *ary, int n)
{
int i, j, m;
dp[1] = 1;
for(i = 2; i <= n; i++)
{
m = 0;
for(j = 1; j < i; j++)
{
if(ary[i] > ary[j] && dp[j] > m)
{
m = dp[j];
}
}
dp[i] = m + 1;
}
m = 0;
for(i = 1; i <= n; i++)
{
if(dp[i] > m)
m = dp[i];
}
return m;
}
int main()
{
int n, i, j, m;
while(scanf("%d", &n) != EOF )
{
for(i = 1; i <= n; i++)
{
scanf("%d", ary + i);
}
printf("%d\n", LIS(ary, n));
}
}
参考:
http://www.wutianqi.com/?p=1850
http://www.chenyajun.com/2010/09/12/4429