您的位置:首页 > 其它

HDU1677:Nested Dolls

2013-08-09 09:24 246 查看
点击打开题目链接

Nested Dolls

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 1923    Accepted Submission(s): 537


Problem Description

Dilworth is the world’s most prominent collector of Russian nested dolls: he literally has thousands of them! You know, the wooden hollow dolls of different sizes of which the smallest doll is contained in the second smallest, and this doll is in turn contained
in the next one and so forth. One day he wonders if there is another way of nesting them so he will end up with fewer nested dolls? After all, that would make his collection even more magnificent! He unpacks each nested doll and measures the width and height
of each contained doll. A doll with width w1 and height h1 will fit in another doll of width w2 and height h2 if and only if w1 < w2 and h1 < h2. Can you help him calculate the smallest number of nested dolls possible to assemble from his massive list of measurements?

 

Input

On the first line of input is a single positive integer 1 <= t <= 20 specifying the number of test cases to follow. Each test case begins with a positive integer 1 <= m <= 20000 on a line of itself telling the number of dolls in the test case. Next follow 2m
positive integers w1, h1,w2, h2, . . . ,wm, hm, where wi is the width and hi is the height of doll number i. 1 <= wi, hi <= 10000 for all i.

 

Output

For each test case there should be one line of output containing the minimum number of nested dolls possible.

 

Sample Input

4
3
20 30 40 50 30 40
4
20 30 10 10 30 20 40 50
3
10 30 20 20 30 10
4
10 10 20 30 40 50 39 51

 

Sample Output

1
2
3
2

 

Source

2008
“Insigma International Cup” Zhejiang Collegiate Programming Contest - Warm Up(3)
 

Recommend

lcy
 

=====================================题目大意=====================================

帮助Dilworth通过嵌套来得到最少的的俄罗斯嵌套娃娃个数。

=====================================算法分析=====================================

本题和HDU1257:最少拦截系统很相似,只不过本题的集合是无序集,而后者则是有序集。

为了应用Dilworth定理求解本题,首先必须将本题的集合有序化,当然有序化是不能改变答案的。

我的选择是按照W升序给娃娃排序,然后娃娃的嵌套条件由Wi<Wj&&Hi<Hj变为i<j&&Wi<Wj&&Hi<Hj。

至于W相同时,按不按H排序,按H怎么排序这都无所谓,并不会改变答案(注:如果你在无聊得怀疑这一点,那只能说你对题目的认

识还不够)。

故而题目所求的就是排序后的娃娃的嵌套关系链的最小划分数,那么由Dilworth定理就可知所求即娃娃的最长不可嵌套关系链的长度。

然后?然后又是WA的血泪史。。。

没办法,只能前往神界求助浩大主神,与浩大主神讨论半天后,发现一个很无语的错误——Dilworh定理用错了。

也怪自己没仔细研究,只是在网上看了Dilworh定理的大致意思,结果顺带把浩大主神也坑了。

Dilworh定理中,不仅要求集合元素之间的关系是偏序关系,也要求该关系的反关系仍是偏序关系!

但是现在(将本题的集合有序化之后),嵌套关系明显是偏序关系(这个就不说了),但是不可嵌套关系呢?

自反性和反对称性显然是有的,而传递性呢?能由Di不可嵌套入Dj(i<j),Dj不可嵌套入Dk(j<k)得到Di不可嵌套入Dk(i<k)么?

这个我就不证明了(用逻辑数学是可以证明的),只给出一组数据说明:D1=(1,2),D2=(2,1),D3=(2,3)。

D1不可嵌套入D2,D2不可嵌套入D3,而D1确可以嵌套入D3,这说明不可嵌套关系不是偏序关系!

那么怎么处理才能让不可嵌套关系变成偏序关系呢?这还是不难想到的,排序的时候,当W相同时按照H从大到小排序即可(嗯,只是

我自己还是不大明白唉)。

======================================代码========================================



/*#######################################[ LOS Templet Of Lyz ]#######################################*/

typedef bool            BOOL;
typedef unsigned int    UINT;

template < typename SEQUTYPE >

//CMP:返回所求序列中前后元素的比较关系("<","<=",">",">="即对应"升序","不降序","降序","不升序")

UINT LOS(SEQUTYPE *Sequ , UINT nSize , BOOL (*CMP)(SEQUTYPE*,SEQUTYPE*) )
{
UINT  Len , *MinID = new UINT [ nSize + 1 ];
MinID[ Len = 1 ] = 0;
for( UINT i = 1 ; i < nSize ; ++i )
{
if( ! CMP( Sequ + MinID[1]  , Sequ + i ) ) { MinID[1] = i;        continue; }
if( CMP( Sequ + MinID[Len]  , Sequ + i ) ) { MinID[ ++Len ] = i;  continue; }
int L = 1 , R = Len;
while( L < R )
{
int M = ( L + R ) >> 1;
if( CMP( Sequ + MinID[ M + 1 ] , Sequ + i ) ) { L = M + 1; }
else { R = M; }
}
MinID[ L + 1 ] = i;
}
delete [] MinID;
return Len;
}

/*#######################################[ LOS Templet Of Lyz ]#######################################*/

#include<cstdio>
#include<algorithm>

using namespace std;

int T,N;

struct DOLL { int W,H; } D[20005];

bool sort_cmp(DOLL& D1,DOLL& D2)
{
return (D1.W<D2.W)||(D1.W==D2.W&&D1.H>D2.H);
}

bool los_cmp(DOLL* D1,DOLL* D2)
{
return !((D1->W<D2->W)&&(D1->H<D2->H));
}

int main()
{
while(scanf("%d",&T)==1) while(T--)
{
scanf("%d",&N);
for(int i=0;i<N;++i)
{
scanf("%d%d",&D[i].W,&D[i].H);
}
sort(D,D+N,sort_cmp);
printf("%d\n",LOS(D,N,los_cmp));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  DP LOS