南邮 OJ 1528 Nested Dolls

Nested Dolls

时间限制(普通/Java) :  1000 MS/ 3000 MS          运行内存限制 : 65536 KByte
总提交 : 57            测试通过 : 12 

比赛描述

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 wand height hwill fit in another doll of width w2
and height hif and only if w< wand h< h2. Can you help him calculate the smallest
number of nested dolls possible to assemble from his massive list of measurements?



输入

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

输出

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

样例输入

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

样例输出

1
2
3
2

提示

undefined

题目来源

Nordic Collegiate Programming Contest 2007





/* Wrong Answer at Test 1
#include<iostream>
#include<algorithm>

#define N 20000
struct doll{
	int w,h;
}d[N];

bool operator<(doll d1,doll d2){
	if(d1.w != d2.w){
		return d1.w < d2.w;
	}
	return d1.h < d2.h;
}

int main(){
	int t,n,i,count;
	scanf("%d",&t);
	while(t--){
		scanf("%d",&n);
		for(i=0;i<n;i++){
			scanf("%d%d",&d[i].w,&d[i].h);
		}
		std::sort(d,d+n);
		count = 1;
		for(i=1;i<n;i++){
			if(d[i-1].w < d[i].w && d[i-1].h < d[i].h){
				;
			}else{
				count++;
			}
		}
		printf("%d\n",count);
	}
}
*/

//Dilworth定理:对于一个偏序集,最少链划分等于最长反链长度。
//Dilworth定理的对偶定理:对于一个偏序集,其最少反链划分数等于其最长链的长度。

#include<iostream>
#include<algorithm>

#define N 20000
struct doll{
	int w,h;
}d[N];

//h[i]:高度的最长递增子序列
int h[N];

//按照宽度从大到小排序,宽度相同时,高度从小到大排序
//然后求高度最长不减子序列(最小集合划分等于最长反链长度)
bool operator<(doll d1,doll d2){
	if(d1.w != d2.w){
		return d1.w > d2.w;
	}
	return d1.h < d2.h;
}

int main(){
	int t,n,i,m,ih;
	scanf("%d",&t);
	while(t--){
		scanf("%d",&n);
		for(i=0;i<n;i++){
			scanf("%d%d",&d[i].w,&d[i].h);
		}
		std::sort(d,d+n);
		m = 0;
		h[0] = 0;
		for(i=0;i<n;i++){
			ih = d[i].h;
			if(ih >= h[m]){				//WA1 反向最长不减序列
				h[++m] = ih;
			}else{						//可以查到前面的某个中去,二分找最小的大于第一个比d[i].h大的值
				int low=0,high=m,mid;
				while(low <= high){
					mid=(low+high)>>1;
					if(h[mid] > ih){
						high = mid-1;	//最后h[high]<=ih
					}else{
						low = mid+1;	//最后h[low]>ih
					}
				}
				h[low] = ih;
			}
		}
		printf("%d\n",m);
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值