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 }
如果有任何意见请在评论区积极留言