关闭

hdu 5714 &&2016 百度之星复赛 1003 拍照(排序+思考)

标签: ACMHDU百度之星排序
607人阅读 评论(0) 收藏 举报
分类:

拍照

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 255    Accepted Submission(s): 87


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

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

![http://acm.hdu.edu.cn/data/images/C715-1003-1.jpg](http://acm.hdu.edu.cn/data/images/C715-1003-1.jpg)
 

Input
第一行为T,表示输入数据组数。

下面T组数据,对于每组数据:

第一行是一个数n(1n104),表示船只的数量。

接下来n行,每行四个整数
x,y,z,d(106x<y106,1z104),表示船只的左端点位置、右端点位置、距离河边的距离,以及航行的方向。d1表示向左航行,1表示向右航行。
 

Output
对第i组数据,输出

Case #i:

然后输出一行,仅包含一个整数,表示最多可以拍到多少完整的船只。
 

Sample Input
3 2 1 3 1 1 2 4 1 -1 2 1 3 1 -1 2 4 1 1 1 1 4 1 1
 

Sample Output
Case #1: 2 Case #2: 1 Case #3: 0
 


solution:

对于船[x,y,z],当x+z>=y-z的时候,可以在[y-z,x+z]这些位置观测到它,那么我们可以处理出来n条线段,我们要求同一垂线交过的线段的数量最多,由于船是可以移动的,那么我们可以固定同一方向的船不动,假设初始在x位置观测往右的船,在y位置观测到往左的船,只要x<=y,那么经过一段时间我们就可以在同一角度观察到这些船。

那么如何求同一垂线交过的线段的数量最多,我们把线段的左端点的值当做1,右端点当成-1,然后就是一个累计的过程,我们要先预处理出每一个端点向左走的船的最大值,最后O(n)扫一遍即可。

总复杂度nlogn

#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 20200;
int n;
struct node 
{
    int x, val, d;
    node(int x=0,int val=0, int d=0) : x(x), val(val), d(d) {}
    bool operator<(const node &a) const
    {
        if (x!=a.x) return x < a.x;
        if (val!=a.val) return val > a.val;
        return d > a.d;
    }
}e[maxn];
int ans[maxn];
int main()
{
    int t, cas = 0, x, y, z, d;
    scanf("%d", &t);
    while (t--) 
    {
        int no = 0;
        scanf("%d", &n);
        for(int i=0;i<n;i++)
        {
            scanf("%d%d%d%d", &x, &y, &z, &d);
            int l = y - z, r = x + z;
            if (l <= r) 
            {
                e[no++] = node(l, 1, d);
                e[no++] = node(r, -1, d);
            }
        }
        sort(e,e+no);
        int ret = 0,now=ans[no] = 0;
        for (int i = no - 1; i >= 0; i--) 
        {
            if (e[i].d < 0 && e[i].val == -1) ++now;
            ans[i] = max(ans[i + 1], now);
            if (e[i].d < 0 && e[i].val == 1) --now;
        }
        now = 0;
        for(int i=0;i<no;i++)
            if (e[i].d > 0) 
            {
                if (e[i].val == 1) now++;
                ret = max(ret, now + ans[i]);
                if (e[i].val == -1) now--;
            }
        printf("Case #%d:\n%d\n", ++cas, ret);
    }
    return 0;
}



0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:111050次
    • 积分:2354
    • 等级:
    • 排名:第17787名
    • 原创:127篇
    • 转载:0篇
    • 译文:0篇
    • 评论:12条
    最新评论