[USACO16JAN] Angry Cows G题解

题目描述

奶牛 Bessie 设计了一款她认为将成为下一个热门视频游戏的游戏:“愤怒的奶牛”。她认为这个游戏的设定是完全原创的:玩家用弹弓将一头奶牛射入一个一维场景中,场景由数轴上不同位置的干草堆组成;奶牛以足够的力量落地,引爆她着陆点附近的干草堆,这可能会引发连锁反应,导致更多的干草堆爆炸。目标是用一头奶牛引发连锁反应,引爆所有干草堆。

有 N 个干草堆位于数轴上不同的整数位置 x1​,x2​,…,xN​。如果一头奶牛以威力 R 被发射到位置 x,这将引发一个“半径为 R”的爆炸,吞噬 x−R…x+R 范围内的所有干草堆。这些干草堆随后会同时爆炸,每个爆炸的半径为 R−1。任何尚未爆炸的干草堆如果被这些爆炸波及,则会同时爆炸,爆炸半径为 R−2,依此类推。

请确定发射一头奶牛所需的最小威力 R,使得如果它落在适当的位置,将引发所有干草堆的爆炸。

输入格式

输入的第一行包含 N(2≤N≤50,000)。接下来的 N 行每行包含一个整数 x1​…xN​(每个整数都在 0…1,000,000,000 范围内)。

输出格式

请输出发射奶牛所需的最小威力 R,以便引爆所有干草堆。答案应四舍五入并精确到小数点后一位。

显示翻译

题意翻译

输入输出样例

输入 #1复制

5
8
10
3
11
1

输出 #1复制

3.0

说明/提示

在这个例子中,一头奶牛以威力 3 发射到位置 5,将立即引爆位置 3 和 8 的干草堆。这些干草堆随后同时爆炸,每个爆炸的半径为 2,吞噬位置 1 和 10 的干草堆,这些干草堆接下来同时爆炸,爆炸半径为 1,吞噬位置 11 的最后一个干草堆,该干草堆最终以爆炸半径 0 爆炸。

思路

DP即可。

代码见下

#include<bits/stdc++.h> 
using namespace std;
long long n,x[50004],f[50004],g[50004];
long long abc(double a1){
    for(int i=n;i>=1;i--){
        if(f[i]+1<=a1){
            for(int j=i;j<=n&&x[j]<=x[i]+2.0*a1;j++){
                if(g[j]+1<=a1){
                    return 1;
                }
            }
            break;
        }
    }
    return 0;
}
int main(){
	cin>>n;
    for(int i=1;i<=n;i++){
        cin>>x[i];
    }
    sort(x+1,x+n+1);
    for(int i=2;i<=n;i++){
        long long l=1,r=i-1,md=i-1;
        while(l<=r){
            long long mid=(l+r)/2;
            if(x[i]-x[mid]<=f[mid]+1){
                md=min(md,mid);
                r=mid-1;
            }
            else{
                l=mid+1;
            }
        }
        f[i]=max(x[i]-x[md],f[md]+1);
        if(md!=1){
            f[i]=min(f[i],max(x[i]-x[md-1],f[md-1]+1));
        }
    }
    for(int i=n-1;i>=1;i--){
        long long l=i+1,r=n,md=i+1;
        while(l<=r){
            long long mid=(l+r)/2;
            if(x[mid]-x[i]<=g[mid]+1){
                md=max(md,mid);
                l=mid+1;
            }
            else{
                r=mid-1;
            }
        }
        g[i]=max(x[md]-x[i],g[md]+1);
        if(md!=n){
            g[i]=min(g[i],max(x[md+1]-x[i],g[md+1]+1));
        }
    }
    double l=0,r=1000000000.00,md=1000000000.00;
    while(l+0.0001<r){
        double mid=(l+r)/2.000;
        if(abc(mid)==1){
            md=min(md,mid);
            r=mid;
        }
        else{
            l=mid;
        }
    }
    printf("%.1lf\n",md);
	return 0;
}

posted @ 2025-10-15 21:50  bz02_2023f2  阅读(9)  评论(0)    收藏  举报  来源