说到偏序集,在离散里的定义是:
设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 代码:
View Code
1
#include
<
stdio.h
>
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 代码:
View Code
1
#include
<
stdio.h
>
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
}