• USACO 2016 January Contest Gold T1: Angry Cows


    题目大意

    奶牛Bessie设计了一个游戏:“愤怒的奶牛”。游戏的原型是:有一些可爆炸的草堆分布在一条数轴的某些坐标上,玩家用弹弓把一头奶牛发射到数轴上。奶牛砸到数轴上的冲击波会引发附近的草堆爆炸,而被引爆的草堆可能会引爆其他草堆。游戏的目标是玩家用一只奶牛炸掉所有的草堆。

    有N (2≤N≤50,000) 个草堆在数轴的不同位置,坐标为x1,x2,….,xn。如果玩家以能量R把奶牛发射到坐标x,就会引爆半径R及以内的的草堆,即坐标范围[x−R,x+R]的草堆都会燃爆,每个被奶牛引爆的草堆又会2次引爆半径R-1及以内的的草堆,2次引爆的草堆又会3次引爆半径R-2及以内的的草堆...直到一次引爆后没有其他草堆被波及或半径为0。

    现在只有1头奶牛,能量为R,请计算如果要引爆所有的草堆,最小的R是多少?

    题目分析

    观察数据范围,n为50000,一般会向O(nlogn)的复杂度思考,所以我们考虑进行二分。

    我们先用 f[i] 记录以i为中心可以向左覆盖前i-1个点的最小半径。 再用 g[i] 记录以i为中心可以向右覆盖至第n个点的最小半径。

    那么我们二分枚举第一次爆炸的半径r。

    枚举i,即第i个草堆为这次爆炸的左边界,再在左边界到右边界的草堆中枚举j,如果f[i]+1<=r并且g[i]+1<=r,则说明这个方案可行。

    考虑再次优化,因为 f数组,g数组 与 草堆坐标 的差都具有单调性(i越大,f[i]越大,反过来,i越小, g[i] 越大),而答案取其中的最大值(f[i]=max(f[now]+1,a[i]-a[now])),

    所以对于 j > i, f[j]的最优决策点一定在f[i]的决策点的右边,所以就可以利用这个性质优化了。

    (建议手动画图模拟)

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int MAXN=5e4+10;
     4 const int Inf=0x3f3f3f3f;
     5 int n;
     6 bool ans1;
     7 int a[MAXN];
     8 int f[MAXN],g[MAXN];
     9 int ans;
    10 inline void Init(){
    11     f[1]=0;g[n]=0;
    12     int now=1;
    13     for(int i=2;i<=n;++i){
    14         while(a[i]-a[now]>=f[now]+1&&now<i-1) ++now;
    15         if(f[now]+1>a[i]-a[now-1]) --now;
    16         f[i]=max(f[now]+1,a[i]-a[now]);
    17 //        cout<<f[i]<<' ';
    18     }
    19 //    puts("");
    20     now=n;
    21     for(int i=n-1;i>=1;--i){
    22         while(a[now]-a[i]>=g[now]+1&&now>i+1) --now;
    23         if(g[now]+1>a[now+1]-a[i]&&now<n) ++now;
    24         g[i]=max(g[now]+1,a[now]-a[i]);
    25 //        cout<<g[i]<<' ';
    26     }
    27 //    puts("");
    28 }
    29 int main(){
    30     ans=Inf;
    31     scanf("%d",&n);
    32     for(int i=1;i<=n;++i)
    33         scanf("%d",&a[i]);
    34     sort(a+1,a+n+1);
    35     Init();
    36     int now=1;
    37     for(int i=1;i<=n;++i){
    38         while(a[i]-a[now]>=(f[now]+1)*2&&now<i-1) ++now;
    39         if(a[i]-a[now-1]<(f[now]+1)*2) --now;
    40         if(max(g[i]+1,max(f[now]+1,(a[i]-a[now])/2))<ans||(max(g[i]+1,max(f[now]+1,(a[i]-a[now])/2))==ans&&((a[i]-a[now])%2<ans1))){
    41             ans=max(g[i]+1,max(f[now]+1,(a[i]-a[now])/2));
    42             if((a[i]-a[now])/2>=f[now]+1&&(a[i]-a[now])/2>=g[i]+1)
    43                 ans1=(a[i]-a[now])%2;
    44             else ans1=0;
    45         }
    46     }
    47     printf("%d",ans);
    48     if(ans1) printf(".5");
    49     else printf(".0");
    50     return 0;
    51 } 
  • 相关阅读:
    P1428 小鱼比可爱
    P5727 【深基5.例3】冰雹猜想
    P1427 小鱼的数字游戏
    P1047 [NOIP2005 普及组] 校门外的树
    P5729 工艺品制作
    P5728 【深基5.例5】旗鼓相当的对手
    CodeSmith使用和语法简介
    系统缓存
    FLV视频转换的利器 ffmpeg.exe
    Vs.Net方向将Excel数据导入到数据库
  • 原文地址:https://www.cnblogs.com/LI-dox/p/11215834.html
Copyright © 2020-2023  润新知