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:\n",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\n",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\n",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\n",ans);
    }

    return 0;
}

  

 


posted @ 2016-05-31 09:54  纸牌  阅读(258)  评论(0编辑  收藏  举报