POJ1065+POJ3636(偏序定理)

说到偏序集,在离散里的定义是:

      设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 }

 


 

posted @ 2011-08-21 13:16  笑巧  阅读(1534)  评论(0编辑  收藏  举报