现在的位置: 首页 > 综合 > 正文

lightoj 1383 Underwater Snipers

2018年02月21日 ⁄ 综合 ⁄ 共 986字 ⁄ 字号 评论关闭

题目大意:在二维坐标系上y=k是分界线,y>k的部分是n个敌人,y<k的部分要安置T个狙击手。每个狙击手的射程是D。问安置好这些狙击手之后,在能将所有的敌人都打掉的情况下最大化狙击手到y=k的距离。

思路:二分答案。然后确定每个敌人可被攻击到的x的区间范围,然后对这些区间做区间覆盖统计需要安狙击手的个数。

struct pp{
    ll x,y;
}pnt[maxn];
struct ppt{
    ll st,ed;
}axis[maxm];
bool cmp(ppt a,ppt b){
    return a.ed<b.ed;
}
ll k,n,s,d;
bool calc(ll mid){
    memset(axis,0,sizeof(axis));
    for(ll i=0;i<n;i++){
        if(pnt[i].y+mid>d)return false;
        ll tmp=(ll)(sqrt(d*d*1.0-1.0*(pnt[i].y+mid)*(pnt[i].y+mid)));
        axis[i].st=pnt[i].x-tmp;
        axis[i].ed=pnt[i].x+tmp;
    }
    ll ans=0;
    sort(axis,axis+n,cmp);
    for(ll i=0;i<n;i++){
        ans++;
        if(ans>s)return false;
        ll t=i+1;
        while(axis[t].st<=axis[i].ed){
            t++;
            if(t>=n)break;
        }
        i=t-1;
    }
    if(ans<=s)return true;
    return false;
}
int main(){
    int T;
    scanf("%d",&T);
    for(int tt=1;tt<=T;tt++){
        scanf("%lld%lld%lld%lld",&k,&n,&s,&d);
        for(ll i=0;i<n;i++){
            scanf("%lld%lld",&pnt[i].x,&pnt[i].y);
            pnt[i].y-=k;
        }
        ll l=0,r=inf;
        ll mid,ans;
        bool has=false;
        while(l<=r){
            mid=(l+r)>>1;
            if(calc(mid))has=true,l=mid+1,ans=mid;
            else r=mid-1;
        }
        printf("Case %d: ",tt);
        if(has)printf("%lld\n",ans);
        else puts("impossible");
    }
    return 0;
}

抱歉!评论已关闭.