杂题专项:UVa 10382

来源:互联网 发布:c#和c语言的区别 编辑:程序博客网 时间:2024/05/10 23:24

一开始以为是一道简单的区间覆盖贪心,区间是离散化的。后来才发现区间是连续的,每个sprinkler覆盖的区间为[p-sqrt(r*r-w*w/4),p+sqrt(r*r+w*w/4)]。

贪心策略在lrj的入门经典里有非常详细的叙述。这里简单说一下,就是已经覆盖的区间全部排除不考虑,然后在剩下的区间中选择能覆盖的最远的那个即可。这里我用的是优先队列的方式实现的。

#include <iostream>#include <fstream>#include <cstring>#include <cstdio>#include <queue>#include <cmath>using namespace std;const double eps=1e-10;int dcmp(double x){    if(fabs(x)<eps) return 0;    else return x<0?-1:1;}int n,l,w;struct interval{    double l,r;    interval(double l=0,double r=0):l(l),r(r){}    bool operator<(const interval& t) const    {        return dcmp(l-t.l)>0||(dcmp(l-t.l)==0&&dcmp(r-t.r)<0);    }};priority_queue<interval> q;int main(){    freopen("in.txt","r",stdin);    while(cin>>n>>l>>w)    {        while(!q.empty()) q.pop();        int p,r;        for(int i=0;i<n;i++)        {            cin>>p>>r;            if(w>2*r) continue;            double t=sqrt(1.0*r*r-1.0*w*w/4);            q.push(interval(p-t,p+t));        }        double cover=0;        int ans=0;        while(!q.empty())        {            if(dcmp(cover-l)>=0) break;            double L=q.top().l,R=q.top().r;            q.pop();            if(dcmp(R-cover)<=0) continue;            else if(dcmp(L-cover)<0) q.push(interval(cover,R));            else if(dcmp(L>cover)>0) break;            else            {                ans++;                cover=R;            }        }        if(dcmp(cover-l)>=0) cout<<ans<<endl;        else cout<<-1<<endl;    }    return 0;}


原创粉丝点击