zoukankan      html  css  js  c++  java
  • 2016 百度之星 复赛

    小明在旅游的路上看到了一条美丽的河,河上有许多船只,有的船只向左航行,有的船只向右航行。小明希望拍下这一美丽的风景,并且把尽可能多的船只都完整地拍到一张照片中。

    小明位于河的边上,并且可以在河边的任意位置进行拍照,照相机的视野恰好为90度角,只能以垂直于河边的方向进行拍照。河上的船只全都可看作是平行于河边的一条线段,跟河边的距离各不相同,有的正在向左移动,有的正在向右移动,但移动速度恰好都是一样的。小明可以等待恰当的时间让尽量多的船只都走进照相机的视野里,你不需要考虑船只之间会互相遮挡视野的情况。

    http://acm.hdu.edu.cn/data/images/C715-1003-1.jpg

     
    思路:
     
    首先得发现这两条规律:
    1.设船到河岸的距离为h,则如果 y-x > 2*h ,则这条船不可能被完整拍到。
    2.设河岸[l,r]范围内能够拍到船,则 l=y-h , r =x+h 。
     
    然后计算每个河岸上的点能够拍到多少条船,两个方向分别处理。
     
    后面的真是不好叙述,如果当面用草稿纸说明会比较方便,看代码吧。数据范围太大,需要离散化。
     
    #include "algorithm"
    #include "iostream"
    #include "cstring"
    #include "cstdio"
    #include "string"
    #include "stack"
    #include "cmath"
    #include "queue"
    #include "set"
    #include "map"
    
    #define lson l , m , rt << 1
    #define rson m + 1 , r , rt << 1 | 1
    
    typedef long long ll;
    typedef unsigned long long ull;
    using namespace std;
    
    const int inf=0x3f3f3f3f;
    const int maxn=1e6+5;
    const int mod = 1e9 +7;
    
    //从右开始顺时针
    int dir4[4][2]= {0,1,1,0,0,-1,-1,0};
    int dir8[8][2]= {0,1,1,1,1,0,1,-1,0,-1,-1,-1,-1,0,-1,1};
    
    int n;
    
    
    int lisan[maxn<<1];
    int lsum[maxn<<1];
    int rsum[maxn<<1];
    
    struct Ship
    {
        int x,y,h,d;
        int l,r;
        bool see()
        {
            return (y-x) <= (h<<1) ;
        }
    } ship[10000+5];
    
    int main()
    {
        //freopen("in_3.txt","r",stdin);
        int t;
        scanf("%d",&t);
        for(int ii=1; ii<=t; ii++)
        {
            printf("Case #%d:
    ",ii);
    
            memset(lsum,0,sizeof lsum);
            memset(rsum,0,sizeof rsum);
    
            scanf("%d",&n);
            int index = 0;
    
            for(int i=0; i<n; i++)
            {
                scanf("%d%d%d%d",&ship[i].x,&ship[i].y,&ship[i].h,&ship[i].d);
                if( !ship[i].see() )
                {
                    //printf("cant see:%d
    ",i);
                    continue;
                }
    
                ship[i].l = ship[i].y-ship[i].h;
                ship[i].r = ship[i].x+ship[i].h;
    
                lisan[index++] = ship[i].l;
                lisan[index++] = ship[i].r;
            }
    
            sort(lisan,lisan+index);
    
            int mm=1;
            for(int i=1;i<index;++i)
            {
                if( lisan[i]!=lisan[i-1] )
                {
                    lisan[mm++]=lisan[i];
                }
            }
    
            for(int i=0;i<n;++i)
            {
                if( !ship[i].see() )
                {
                    //printf("cant see:%d
    ",i);
                    continue;
                }
    
                int l = lower_bound(lisan,lisan+mm,ship[i].l) - lisan;
                int r = lower_bound(lisan,lisan+mm,ship[i].r) - lisan;
    
                if( ship[i].d==1 ) //right
                {
                    rsum[l] ++;
                    rsum[r+1]--;
                }
                else
                {
                    lsum[l] ++;
                    lsum[r+1]--;
                }
            }
    
            for(int i=1 ;i<mm;++i)
            {
                rsum[i] +=rsum[i-1];
                lsum[i] +=lsum[i-1];
            }
    
            int rm = 0,ans=0;
            for(int i=0;i<mm;++i)
            {
                rm = max(rm,rsum[i]);
                ans = max(ans,rm+lsum[i]);
            }
            printf("%d
    ",ans);
        }
    
        return 0;
    }
    

      

     


  • 相关阅读:
    [LeetCode]Sort List
    [LeetCode]Single Number II
    合并两个排序的列表
    翻转链表
    链表中倒数第k个结点
    调整数组顺序使奇数位于偶数前面
    数值的整数次方
    二进制中1的个数
    矩形覆盖
    变态跳台阶
  • 原文地址:https://www.cnblogs.com/bruce27/p/5544909.html
Copyright © 2011-2022 走看看