说到偏序集,在离散里的定义是:
设R为非空集合A上的关系,如果R是自反的、反对称的和传递的,则称R为A上的偏序关系,简称偏序,记作≤。
偏序是在集合X上的二元关系≤(这只是个抽象符号,不是“小于或等于”),它满足自反性、反对称性和传递性。即,对于X中的任意元素a,b和c,有:
自反性:a≤a;
反对称性:如果a≤b且b≤a,则有a=b;
传递性:如果a≤b且b≤c,则a≤c 。
带有偏序关系的集合称为偏序集。
令(X,≤)是一个偏序集,对于集合中的两个元素a、b,如果有a≤b或者b≤a,则称a和b是可比的,否则a和b不可比。
在X中,对于元素a,如果任意元素b,由b≤a得出b=a,则称a为极小元。
一个反链A是X的一个子集,它的任意两个元素都不能进行比较。
一个链C是X的一个子集,它的任意两个元素都可比。
任何集合A上的恒等关系,集合的幂集P(A)上的包含关系,实数集上的小于等于关系,正整数集上的整除关系等都是偏序关系。
那么现在,我们重点利用集合的包含关系来解决poj1065、poj3636这两题。
POJ1065 题意:有n个木棒,分别不同的长度和不同的重量,一个机器需要处理这些木棒,如果第i+1个木棒的重量和长度都>=第i个处理的木棒,那么将不会耗费时间,否则需要增加一个单位的时间,问最少需要多少时间处理完(包括机器启动的时间)。
POJ3636 题意:套娃娃,只有当 w1 < w2 && h1 < h2 时才能将娃娃(w1,h1)套在娃娃(w2,h2)里面,问最少需要多少嵌套的娃娃。
算法:二者区别在于前者是大于等于关系,而后者必须是大于的。这就导致了二者排序的方式不一样,第一个参数都是从小到大排,但是第二个参数就有所区别了。前者要求是包含 =的,所以第2个参数也是从小到大排;而后者则不包含 = 所以要从大到小排 。因为w升序,h降序可以保证w相等时,一定不会出现覆盖的情形。
POJ1065 代码:
2 #include < algorithm >
3 using namespace std;
4 #define Max 5005
5 struct node{
6 int l,w;
7 }n[Max];
8
9 int an[Max];
10 bool cmp(node x,node y)
11 {
12 if (x.w == y.w) return x.l < y.l;
13 return x.w < y.w;
14 }
15
16 int main()
17 {
18 int t,m,i,j;
19 scanf( " %d " , & t);
20 while (t -- )
21 {
22 scanf( " %d " , & m);
23 for (i = 0 ;i < m;i ++ )
24 scanf( " %d%d " , & n[i].l, & n[i].w);
25 sort(n,n + m,cmp);
26 int num = 0 ;
27 for (i = 0 ;i < m;i ++ )
28 {
29 int flag = 0 ;
30 for (j = 0 ;j < num;j ++ )
31 if (n[i].l >= an[j])
32 {
33 an[j] = n[i].l;
34 flag = 1 ;
35 break ;
36 }
37 if ( ! flag) an[num ++ ] = n[i].l;
38 }
39 printf( " %d\n " ,num);
40 }
41 return 0 ;
42 }
POJ3636 代码:
2 #include < algorithm >
3 using namespace std;
4 #define Max 20001
5 struct D{
6 int w,h;
7 }d[Max];
8 D dd[Max];
9
10 bool cmp(D x,D y) // w升序,h降序可以保证w相等时,一定不会出现覆盖的情形。
11 {
12 if (x.w == y.w) return x.h > y.h;
13 return x.w < y.w;
14 }
15 int main()
16 {
17 int n,i,j,m;
18 scanf( " %d " , & n);
19 while (n -- )
20 {
21 int result = 0 ;
22 scanf( " %d " , & m);
23 for (i = 0 ;i < m;i ++ )
24 scanf( " %d%d " , & d[i].w, & d[i].h);
25 sort(d,d + m,cmp);
26 for (i = 0 ;i < m;i ++ )
27 {
28 int flag = 0 ;
29 for (j = 0 ;j < result;j ++ )
30 if (d[i].w > dd[j].w && d[i].h > dd[j].h)
31 {
32 dd[j] = d[i];
33 flag = 1 ;
34 break ;
35 }
36 if ( ! flag) dd[result ++ ] = d[i];
37 }
38 printf( " %d\n " ,result);
39 }
40 return 0 ;
41 }