dilworth定理

定义::在数学理论中的序理论组合数学中,Dilworth定理根据序列划分的最小数量的链描述了任何有限偏序集的宽度。其名称取自数学家Robert P. Dilworth。

定理内容::

反链是一种偏序集,其任意两个元素不可比;而链则是一种任意两个元素可比的偏序集。Dilworth定理说明,存在一个反链A与一个将序列划分为链族P的划分,使得划分中链的数量等于集合A的基数。当存在这种情况时,对任何至多能包含来自P中每一个成员一个元素的反链,A一定是此序列中的最大反链。同样地,对于任何最少包含A中的每一个元素的一个链的划分,P也一定是序列可以划分出的最小链族。偏序集的宽度被定义为A与P的共同大小。
另一种Dilworth定理的等价表述是:在有穷偏序集中,任何反链最大元素数目等于任何将集合到链的划分中链的最小数目。一个关于无限偏序集的理论指出,在此种情况下,一个偏序集具有有限的宽度w,当且仅当它可以划分为最少w条链。 [1] 

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

即:链的最少划分数 = 反链的最长长度

例::

1 7 8  2 3 4

反链:最长不上升子序列(如:(7,2))长度 = 2;

即:按升序划分,最少的链划分数为2,为(1,2,3,4)和(7,8)。

 

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

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

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

例::  3 2 2 1 4

最少的最长不升子序列的数目::《3 2 2 1》《4》==最长上升子序列长度(2);

洛谷  P1020 导弹拦截

题意求最少导弹拦截系统(最少的最长的不生链分数)==最长的升序列长度

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 const int maxn=1e5+5;
 5 int dp[maxn];
 6 int a[maxn],ma[maxn];
 7 int main()
 8 {
 9     int n;
10     char c;
11     int k=0;
12     while(~scanf("%d%c",&n,&c))
13     {
14         ma[k++]=n;
15         if(c=='
'){break;}
16     }
17     a[1]=ma[k-1];
18     int len=1;
19     for(int i=k-2;i>=0;i--)
20     {
21         if(ma[i]>=a[len]){
22             a[++len]=ma[i];
23         }
24         else {
25             int pos=upper_bound(a+1,a+len+1,ma[i])-a;
26             a[pos]=ma[i];
27         }
28     }
29     dp[1]=ma[1];
30     int let=1;
31     for(int i=2;i<k;i++)
32     {
33         if(ma[i]<=dp[let]){
34             int pos=lower_bound(dp+1,dp+let+1,ma[i])-dp;
35             dp[pos]=ma[i];
36         }
37         else {
38             dp[++let]=ma[i];
39         }
40     }
41     printf("%d
%d
",len,let);
42     return 0;
43 }

洛谷  P1233 木棍加工

题目描述

一堆木头棍子共有n根,每根棍子的长度和宽度都是已知的。棍子可以被一台机器一个接一个地加工。机器处理一根棍子之前需要准备时间。准备时间是这样定义的:

第一根棍子的准备时间为1分钟;

如果刚处理完长度为L,宽度为W的棍子,那么如果下一个棍子长度为Li,宽度为Wi,并且满足L>=Li,W>=Wi,这个棍子就不需要准备时间,否则需要1分钟的准备时间;

计算处理完n根棍子所需要的最短准备时间。比如,你有5根棍子,长度和宽度分别为(4, 9),(5, 2),(2, 1),(3, 5),(1, 4),最短准备时间为2(按(4, 9)、(3, 5)、(1, 4)、(5, 2)、(2, 1)的次序进行加工)。

输入格式

第一行是一个整数n(n<=5000),第2行是2n个整数,分别是L1,W1,L2,w2,…,Ln,Wn。L和W的值均不超过10000,相邻两数之间用空格分开。

输出格式

仅一行,一个整数,所需要的最短准备时间。

输入输出样例

输入 #1
5
4 9 5 2 2 1 3 5 1 4
输出 #1
2
 分析::按长度大到小排序,若相同按宽度大到小排序,最少的最长的不升链分数==最长的上升序列长度,就可以做出来了
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 const int maxn=5005;
 5 int a[maxn];
 6 struct node
 7 {
 8     int x,y;
 9 }ma[maxn];
10 bool cmp(node A,node B)
11 {
12     if(A.x==B.x){
13         return A.y>B.y;
14     }
15     else{
16         return A.x>B.x;
17     }
18 }
19 int main()
20 {
21     int n;
22     scanf("%d",&n);
23     for(int i=1;i<=n;i++)
24     {
25         scanf("%d%d",&ma[i].x,&ma[i].y);
26     }
27     sort(ma+1,ma+n+1,cmp);
28     a[1]=ma[1].y;
29     int len=1;
30     for(int i=2;i<=n;i++)
31     {
32         if(ma[i].y>a[len]){
33             a[++len]=ma[i].y;
34         }
35         else{
36             int pos=lower_bound(a+1,a+len+1,ma[i].y)-a;//二分较快
37             a[pos]=ma[i].y;
38         }
39     }
40     printf("%d
",len);
41     return 0;
42 }
纵使单枪匹马,也要勇闯天涯
原文地址:https://www.cnblogs.com/sj-gank/p/11417753.html