【codevs1044】导弹拦截问题与Dilworth定理

2020-05-31 23:25:41 浏览数 (1)

题目描述 Description

    某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。

输入描述 Input Description

输入导弹依次飞来的高度(雷达给出的高度数据是不大于30000的正整数)

输出描述 Output Description

输出这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。

样例输入 Sample Input

389 207 155 300 299 170 158 65 

样例输出 Sample Output

6

2

数据范围及提示 Data Size & Hint

导弹的高度<=30000,导弹个数<=20

分析:

第一问是求最长不上升序列,通过状态转移方程:

代码语言:javascript复制
dp[j]=1(j← 0 to 导弹个数-1)
代码语言:javascript复制
dp[j]=max{dp[j],dp[k] 1}(high[k]>=high[j])

再看第二问,求的是最少分几个最长不上升序列。接下来要涉及到一个优美的定理(不要问为什么优美)。

Dilworth定理:对于一个偏序集,最少链划分等于最长反链长度。

Dilworth定理的对偶定理:对于一个偏序集,其最少反链划分数等于其最长链的长度。

也就是说把一个数列划分成最少的最长不升子序列的数目就等于这个数列的最长上升子序列的长度

因此第二问的状态转移方程是:

dp2[j]=1(j← 0 to 导弹个数-1)

dp2[j]=max{dp2[j],dp2[k] 1}(high[k]<=high[j])

代码:

代码语言:javascript复制
#include<iostream>
#include<algorithm>
using namespace std;
const int maxdaodan=20 5;
int dp[maxdaodan],dp2[maxdaodan],high[maxdaodan],ans=0,ans2=0,daodan=0;
int main()
{
    while(cin>>high[daodan])
    {
        dp[daodan]=1;
        dp2[daodan]=1;
        daodan  ;
    }
    for(int j=0; j<daodan; j  )
    {
        for(int k=0; k<j; k  )
        {
            if(high[k]>=high[j])
                dp[j]=max(dp[j],dp[k] 1);
            if(high[k]<=high[j])
                dp2[j]=max(dp2[j],dp2[k] 1);
        }
        ans=max(ans,dp[j]);
        ans2=max(ans2,dp2[j]);
    }
    cout<<ans<<endl<<ans2<<endl;
}

想明白Dilworth定理的学霸们,请继续阅读:

偏序集的定义:偏序是在集合X上的二元关系≤(这只是个抽象符号,不是“小于或等于”,它满足自反性、反对称性和传递性)。即,对于X中的任意元素a,b和c,有:

(1)自反性:a≤a;

(2)反对称性:如果a≤b且b≤a,则有a=b;

(3)传递性:如果a≤b且b≤c,则a≤c 。

带有偏序关系的集合称为偏序集。

令(X,≤)是一个偏序集,对于集合中的两个元素a、b,如果有a≤b或者b≤a,则称a和b是可比的,否则a和b不可比。

在这个例子(反链)中元素Ri<=Rj是指(i<=j) and (ai>=aj)

一个反链A是X的一个子集,它的任意两个元素都不能进行比较。

一个链C是X的一个子集,它的任意两个元素都可比。

【定理】

在X中,对于元素a,如果任意元素b,都有a≤b,则称a为极小元。

定理1:令(X,≤)是一个有限偏序集,并令r是其最大链的大小。则X可以被划分成r个但不能再少的反链。

其对偶定理称为Dilworth定理:

令(X,≤)是一个有限偏序集,并令m是反链的最大的大小。则X可以被划分成m个但不能再少的链。

虽然这两个定理内容相似,但第一个定理证明要简单一些。此处就只证明定理1。

证明:设p为最少反链个数

(1)先证明X不能划分成小于r个反链。由于r是最大链C的大小,C中任两个元素都可比,因此C中任两个元素都不能属于同一反

链。所以p>=r。

(2)设X1=X,A1是X1中的极小元的集合。从X1中删除A1得到X2。注意到对于X2中任意元素a2,必存在X1中的元素a1,使得

a1<=a2。令A2是X2中极小元的集合,从X2中删除A2得到X3……,最终会有一个Xk非空而Xk 1为空。于是A1,A2,…,Ak就是X的

反链的划分,同时存在链a1<=a2<=…<=ak,其中ai在Ai内。由于r是最长链大小,因此r>=k。由于X被划分成了k个反链,因此

r>=k>=p。

(3)因此r=p,定理1得证。

【解决】

要求最少的覆盖,按照Dilworth定理

最少链划分 = 最长反链长度

所以最少系统 = 最长导弹高度上升序列长度。

0 人点赞