搜集战舰的游戏

来源:互联网 发布:安卓电视直播软件 知乎 编辑:程序博客网 时间:2024/04/27 22:03

题意:

给定一个成直线排布的地图,和某人拥有的战舰数量,以及每艘战舰所占用的空间大小,按时间顺序给定一些炮弹轰击的位置,问怎样摆放船只,可以让船只最晚受到炮击,并输出该炮弹序号,若可以完全避开,则输出-1。

分析:

用二分法,按炮弹的落地位置将地图分为若干部分,判断每一部分能容纳的战舰数量,若可容纳的战舰数量大于等于拥有的战舰数则说明不能击中战舰,即返回-1。

代码如下:

#include <cstdio>#include <algorithm>#include <cmath>using namespace std;const int N = 2e5 + 10;int n, k, m, A;int pos[N], r[N];//pos数组存放炮弹的落地点int calc(int v) {   return (v + 1) / (A + 1);}bool check(int p) {   int cnt = 0;   for(int i = 1; i <= p; ++i) r[i] = pos[i];//记录可能落炮弹的位置   sort(r + 1, r + p + 1);//将炮弹的落地点按大小排序   for(int i = 2; i <= p; ++i)   {       int len = r[i] - r[i - 1] - 1;       cnt += calc(len);//计算每两个炮弹之间距离为多少,此时能容纳多少辆战舰   }   cnt += calc(r[1] - 1);//最远的地方可以容纳的战舰   cnt += calc(n - r[p]);//最近的地方可以容纳的战舰   if(cnt >= k) return true;//如果可以容纳战舰的总和大于等于所拥有战舰数量,则返回真   else return false;}int main(){    while(~scanf("%d%d%d", &n, &k, &A))    {        scanf("%d", &m);        for(int i = 1; i <= m; ++i) scanf("%d", &pos[i]);//炮弹降落的位置        int low = 1, high = m;        while(low < high)        {            int mid = (low + high) >> 1;//二分法,将地图分成两半            if(!check(mid)) high = mid;            else low = mid + 1;        }        if(check(m))           puts("-1");        else           printf("%d\n", low);    }    return 0;}



0 0
原创粉丝点击