Cpp环境【NOIP practice】【BSOJ1878】【Vijos1172】 山头狙击战

【问题描述】  

  Lucky为了掩护大部队,单枪匹马同敌人周旋,后来被敌人包围在某山头……等等,为什么怎么听怎么像狼牙山五壮士!不过不用着急,这次Lucky携带了足够的弹药,完全可以将涌上来的敌人一个一个干掉。Lucky是个神枪手,只要他的枪膛中有子弹,他就能将在他射程m(用从敌人位置到山头的直线距离算)以内的一个敌人瞬间射杀。但如果在射程内没有敌人,出于节约子弹考虑和面子问题,Lucky会等待敌人靠近然后射击。
  正当Lucky为自己的强大而自我膨胀时,他忽然发现了一个致命的失误:他携带的枪是单发枪,每射出一发子弹都必须花k秒钟的时间装子弹。而凶残的敌人才不会花时间等你换子弹呢。他们始终在以1m/s的速度接近山头。而如果在一个敌人到达山头时Lucky无法将他击毙,那么我们可怜的Lucky就将牺牲在敌人的刺刀下。现在Lucky用心灵感应向你发出求助:要保住自己的性命并且歼灭所有敌人,Lucky最多只能用多少时间给枪装上一发子弹?
  说明:假设一开始Lucky的枪中就有一发子弹,并且一旦确定一个装弹时间,Lucky始终会用这个时间完成子弹的装卸。希望你能帮助Lucky脱离险境。

【输入格式】  

  第一行有两个整数n和m,n代表敌人个数,m代表Lucky的射程。接下来有n行,每行一个整数di,代表每个敌人一开始相对山头的距离(单位为米)。

【输出格式】  

  仅有一个整数,代表Lucky的换弹时间(单位为秒)。

【输入样例】  

6 100
236
120
120
120
120
120

【输出样例】  

25

【数据范围】  

50%的数据有:2<=n<=1000
100%的数据有:2<=n<=100,000; 1<=m<=10,000,000;1<=di<=10,000,000

【思路梳理】

不解释为什么使用二分猜答案和二分猜答案的细节,直接描述check函数的写法。
首先肯定是先排序确定好每一个敌人的距离。贪心地,这个顺序也是我们依次击毙敌人的顺序(肯定优先射杀更近的敌人来为击杀后面的敌人腾出更多时间)。
那么接下来怎么办?
最容易想到的办法是模拟,用一个新的数组dist1来判断Lucky能否在他抵达山头之前击毙。但这样显得复杂,而且有点慢。
于是考虑使用一个time计时器来记录当前的时间。如果最近敌人在射程m以外,Lucky就要等待他进入射程,计时器加上这个敌人进入射程的时间(值得一提的是这个时间是相对于开始战斗的时间,距离是相对于初始距离而言)。如果某一时刻time>=dist[i],击毙这一名敌人的时间已经大于了他接近神射手所需的时间,说明Lucky已经阵亡,这个装填时间太长。每一次击杀敌人后,Lucky都要装弹,time+reload_time。

【Cpp代码】
#include
#include
#include
#include
#define maxn 100005
using namespace std;
int n,m;
vector<int>dist;

bool judge(int reload_time)
{
    int time=0;//从开始到击杀下一个敌人所需要的时间 
    for(int i=0;iif(time>dist[i])    return false;//击杀第i个敌人的时间已经大于了他接近神射手所需的时间
        if(time//下一个最近的敌人还没有进入射程,Lucky等待他进入射程 
        time+=reload_time;//击毙第i名敌人,Lucky装填子弹 
    }
    return true;
}

void solve()
{
    int s=0,d=m,ans;
    while(s<=d)
    {
        int mid=s+d>>1;
        if(judge(mid))  ans=mid,s=mid+1;
        else d=mid-1;
    }
    printf("%d",ans);
}
int main()
{
    //freopen("in.txt","r",stdin);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)   
    {
        int x;
        scanf("%d",&x);
        dist.push_back(x);
    }
    sort(dist.begin(),dist.end());
    solve();
    return 0;
}

你可能感兴趣的:(基础算法之五,贪婪的心,分治算法之二分猜答案,难度评级,Normal)