hdu1677 贪心

题意:

对于给出的n个俄罗斯套娃,要求将这n个套起来(满足w1 < w2 && h1 < h2才能套进去),最后输出最少剩下的套娃个数(尽可能去套起来)

题目分析:

朴素的贪心,类似于最少导弹拦截系统那题,首先一样的是排序,但是排序的要先按w升序,在w相同的时候用降序排,为什么呢,这里想举个例子我们输入的为(20 13)(20 14)(20 15)(30 20)(40 14)如果按照w和h都为升序,然后我们按照贪心的思想,将第一个作为基准,从第二个开始取出来和已有的比较,如果能套就套上去,不能套就后移,尝试完所有的已有的都不能套上去则将这个套娃放入数组的最后(新建一个),那么此时这个方案的最终情况如下:

30 20

20 13  20 14  20 15  40 14

而如果我们按照w升序,而h降序排序后(20 15)(20 14)(20 13)(30 20)(40 14)方案的最终如下:

30 20        40 14

20 15  20 14  20 13

此时我们明白,对于w从小到大排序之后,我们每取一个的后一个w一定满足大于等于前者(w已经升序排序),而每一个后面的套娃应该与前面的高度从大到小去比较,尽可能将小的高度留给后面虽然宽度更大但是高度可能较小的套娃(可以套上去而不至于新开一个)

代码:

 1 #include<iostream>
 2 #include<string.h>
 3 #include<algorithm>
 4 #include<cstdlib>
 5 #include<cmath>
 6 using namespace std;
 7 
 8 struct Node{
 9     int w, h;
10 }k[20005], ans[20005];
11 
12 bool cmp(Node a, Node b){
13     if(a.w == b.w) return a.h > b.h;
14     else return a.w < b.w;
15 }
16 
17 int main(){
18     int t;
19     scanf("%d", &t);
20     while(t--){
21         int n;
22         scanf("%d", &n);
23         for(int i = 1; i <= n; i++) scanf("%d%d", &k[i].w, &k[i].h);
24         sort(k+1, k+n+1, cmp);
25         int cnt = 1;
26         ans[cnt].w = k[cnt].w;
27         ans[cnt].h = k[cnt].h;
28         for(int i = 2; i <= n; i++){
29             int flag = 0;
30             for(int j = 1; j <= cnt; j++){
31                 if(ans[j].w < k[i].w && ans[j].h < k[i].h){
32                     flag = 1;
33                     ans[j].w = k[i].w;
34                     ans[j].h = k[i].h;
35                     break;
36                 }
37             }
38             if(flag == 0){
39                 cnt++;
40                 ans[cnt] = k[i]; 
41             }
42         }
43         printf("%d\n", cnt);
44     }   
45     return 0;
46 }

 

 

posted on 2019-11-19 15:12  白泽talk  阅读(80)  评论(0编辑  收藏  举报