读书人

HDU OJ 1677 Nested Dolls【2分LIS】

发布时间: 2013-03-19 17:22:05 作者: rapoo

HDU OJ 1677 Nested Dolls【二分,LIS】

原题连接:http://acm.hdu.edu.cn/showproblem.php?pid=1677

题意:每组测试数据给n个硬币,现在给你这n个硬币的长和高,若一硬币的长和高都小于另一个硬币,则这来个硬币可嵌套为一个硬币。。求最后剩余的最小硬币数。

思路:首先肯定能想到的是 贪心,不停遍历,不停更新。。复杂度 n*n (超时!!),然后又想到和以前做的题类似,有想到 二分图匹配之最小路径覆盖。。这个题数据20000个点,铁定超时。。看了xiaod的博客,看到一种牛叉的算法。。首先 按照 长 对硬币排序(由大到小),然后对于所有硬币的高组成的一个序列,求最长单调递增子序列的个数,这就是问题的解!仔细想一下,列出求的单调递增序列对应的硬币,发现他们任意两两都是不能嵌套的。然后其余的硬币都可以嵌套进入这些硬币中!这个想法太神奇了……对于求最长单调递增子序列,要是动态规划复杂度n*n,还是要超时的。这里再利用二分查找,复杂度O(n*logn),就能AC了……

代码:

#include <iostream>#include <stdio.h>#include <algorithm>using namespace std;int Ans[22000],sum;struct Doll{    int x;    int y;    bool operator<(const Doll&t)const    {        return x>t.x||x==t.x&&y<t.y;    }}d[22000];bool cmp(Doll t1,Doll t2){    if(t1.x!=t2.x)        return t1.x>t2.x;    else        return t1.y<t2.y;}void Binary(int dd){    int x=0,y=sum;    while(x<y)    {        int mid = (x+y)/2;        if(Ans[mid]>dd)            y=mid;        else            x=mid+1;    }    Ans[y]=dd;}int main(){    int i,j,n,ncase;    cin>>ncase;    while(ncase--)    {        cin>>n;        for(i=0;i<n;i++)            scanf("%d%d",&d[i].x,&d[i].y);        sort(d,d+n);        sum=0;        Ans[sum++]=d[0].y;        for(i=1;i<n;i++)        {            if(d[i].y>=Ans[sum-1])                Ans[sum++]=d[i].y;            else                Binary(d[i].y);        }        cout<<sum<<endl;    }    return 0;}


读书人网 >编程

热点推荐