dilworth定理
定义::在数学理论中的序理论与组合数学中,Dilworth定理根据序列划分的最小数量的链描述了任何有限偏序集的宽度。其名称取自数学家Robert P. Dilworth。
定理内容::
偏序集的两个定理:
定理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=='\n'){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\n%d\n",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,相邻两数之间用空格分开。
输出格式
仅一行,一个整数,所需要的最短准备时间。
输入输出样例
5 4 9 5 2 2 1 3 5 1 4
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\n",len); 41 return 0; 42 }