题目描述
有m个盒子,第i个盒子的长尾hi,宽为wi。如果两个盒子i,j满足hi<hj且wi<wj,则盒子i能够放入盒子j。按照上述要求堆放盒子,则最少能剩下多少堆?
输入
第一行有一个正整数 t ,表示数据组数(不多于20)。每组数据第一行为m,表示盒子个数,1 ≤ m ≤ 20000。接下来一样有2m个正整数w1, h1,w2, h2, ... ,wm, hm,分别表示盒子尺寸。其中对于任何i,1 ≤ wi, hi ≤ 10000.
输出
每一组测试数据输出一样,为最少的堆数。
样例输入
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
看到题目大家都觉得很熟悉,不就是dp问题吗?可是n=20000;不能用n^2的dp,只能用nlgn的方法
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; const int maxn=20001; struct node { int x,y; }box[maxn]; int a[maxn]; bool cmp(node xx,node yy) { if (xx.x==yy.x) return xx.y<yy.y; else return xx.x>yy.x; } void find(int x,int y,int v) { while (x<y) { int m=x+(y-x)/2; if (a[m]<=v) x=m+1; else y=m; } a[x]=v; } int main() { int n,len,t; scanf("%d",&t); while (t--) { scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%d%d",&box[i].x,&box[i].y); sort(box+1,box+n+1,cmp); len=1;a[1]=box[1].y; for (int i=2;i<=n;i++) { if (box[i].y>=a[len]) a[++len]=box[i].y; else { find(1,len,box[i].y); } } printf("%d\n",len); } return 0; }
hust 1463 - 第二届“华为杯”初赛题目H,布布扣,bubuko.com
原文:http://www.cnblogs.com/chensunrise/p/3731086.html