HDU1677:Nested Dolls

点击打开题目链接

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
 

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;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值