EOJ-1765 Nested Dolls
http://acm.cs.ecnu.edu.cn/problem.php?problemid=1765
题意:给出一系列物体的宽与高,满足w1<w2且h1<h2的情况下可以把物品1装在物品2中(可以看成一个),问最少剩余几个物品。
思路:为方便则先按宽度排序,就保证后面的物品一定不能放进前面的物品中,每次只要对每个物品前面的物品进行搜索(即宽度小于该物品),若满足高度比该物品高度小的就列入候选,最终选择候选最大的那个物品装进该物品中(贪心思路,如果每次把前面物品装进后面物品中尽可能选择最大的,那剩余小的可以尽可能让后续的物品装进,而对于某物品来说,选择谁去装它并不会影响结果),若找不到满足要求的物品,则说明需要另开一个了。每次装完后需要更新把装进去的物品从能选择的集合中删除。
而对于相同宽度的物品,高度必须按照降序排序,这样进行前面的搜索时就不会把相同宽度的也纳入候选
实现用了multiset (不去重的集合) 和low_bound (找到第一个大于等于指定值的元素)
1 #include<map> 2 #include<set> 3 #include<list> 4 #include<cmath> 5 #include<ctime> 6 #include<queue> 7 #include<stack> 8 #include<cctype> 9 #include<cstdio> 10 #include<string> 11 #include<vector> 12 #include<cstdlib> 13 #include<cstring> 14 #include<iostream> 15 #include<algorithm> 16 using namespace std; 17 struct node{ 18 int w,h; 19 }a[20005]; 20 bool cmp(node a,node b){ 21 if(a.w!=b.w) 22 return a.w<b.w; 23 else 24 return a.h>b.h; 25 } 26 int main(){ 27 //freopen("1765#1.in","r",stdin); 28 //freopen("out.txt","w",stdout); 29 int T; 30 cin>>T; 31 while(T--){ 32 int n; 33 scanf("%d",&n); 34 for(int i=0;i<n;i++) 35 scanf("%d%d",&a[i].w,&a[i].h); 36 sort(a,a+n,cmp); 37 multiset<int> s; 38 int cnt=0; 39 for(int i=0;i<n;i++){ 40 multiset<int>::iterator it=s.lower_bound(a[i].h); 41 if(it==s.begin()) cnt++; //找不到比它更小的元素 42 else s.erase(--it); //找到则删除之前的元素(即小于给定值的极大值) 43 s.insert(a[i].h); 44 } 45 printf("%d\n",cnt); 46 } 47 return 0; 48 }