Chinaunix首页 | 论坛 | 博客
  • 博客访问: 39407
  • 博文数量: 22
  • 博客积分: 1130
  • 博客等级: 少尉
  • 技术积分: 280
  • 用 户 组: 普通用户
  • 注册时间: 2006-10-11 17:20
文章分类

全部博文(22)

文章存档

2010年(3)

2009年(19)

我的朋友
最近访客

分类:

2009-10-31 23:04:24

题意有些难理解:事件两个属性(t,x),现在给定N个事件,另一个输入M,求在一个最近的时间点,在这个时间点内能通过M个诱发事件使得N个事件发生。

观察图中和题目中的公式,如果确定一个t2,那么我们要判断t2能否通过M个事件诱发所给的N个事件。如果t时刻能满足,那么t-1,t-2 等等前面的时刻也能满足(通俗的理解就是t越小,那么所能覆盖的面积越大)。要求最大的,那么能二分枚举t,从N个事件中t最小的作为上界,一个很小的数作为下界。另求一个t,最少需要多少个事件才能诱发所给的事件,通过给N个事件按x排序,维持一个x的范围,不断缩小,如果满足不了则增加一个点。


//948K    454MS
//二分 + 排序
#include <iostream>
#include <numeric>
#include <limits>
using namespace std;

const int MAX=100001;
int M,N;

typedef struct _Node{
    int t;
    int x;
}Node;

Node nodes[MAX];

int cmp(const void* left,const void* right)
{
    return ((Node*)left)->x-((Node*)right)->x;
}

bool Greedy(int t_now)
{
    int x_max;
    int x_min;
    int need=0;
    bool have_one=false;
    for(int i=0;i<N;i++)
    {
        if(!have_one)
        {
            x_max=nodes[i].x+abs(t_now-nodes[i].t);
            x_min=nodes[i].x-abs(t_now-nodes[i].t);
            have_one=true;
            need++;
            if(need>M)
                return false;
        }
        else
        {
            int t_max=nodes[i].x+abs(t_now-nodes[i].t);
            int t_min=nodes[i].x-abs(t_now-nodes[i].t);
            if(t_min>x_min)
                x_min=t_min;
            if(t_max<x_max)
                x_max=t_max;
            if(x_max<x_min)
            {
                have_one=false;
                i--;
            }
        }
    }
    if(need>M)
        return false;
    else
        return true;
}


int main()
{
    int K;
    scanf("%d",&K);
    int NUM=0;
    while(K--)
    {
        int lest=numeric_limits<int>::max();
        scanf("%d%d",&N,&M);
        for(int i=0;i<N;i++)
        {
            scanf("%d%d",&nodes[i].t,&nodes[i].x);
            if(nodes[i].t<lest)
                lest=nodes[i].t;
        }
        qsort(nodes,N,sizeof(Node),cmp);

        int up=lest;
        int down=-4000000;
        
        while(up>=down)
        {
            int mid=(up+down)/2;
            //cout<
            if(Greedy(mid))
                down=mid+1;
            else
                up=mid-1;
        }
        printf("Case %d: %d\n",++NUM,up);
    }
}


阅读(410) | 评论(0) | 转发(0) |
0

上一篇:深度探索C 读书笔记

下一篇:POJ 1788

给主人留下些什么吧!~~