Codeforces 567D One-Dimensional Battle Ships

本文探讨了在有限长度的板上放置特定数量和尺寸的战舰的算法,通过数学公式计算最大战舰数,并使用集合数据结构实现射击操作后的布局更新。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

One-Dimensional Battle Ships

题目链接:

http://codeforces.com/problemset/problem/567/D

解题思路:

First, we should understand when the game ends. It will happen when on the n-sized board it will be impossible to place k ships of size a. For segment with length len we could count the maximum number of ships with size a that could be placed on it. Each ship occupies a + 1cells, except the last ship. Thus, for segment with length len the formula will look like  (we add "fictive" cell to len cells to consider the last ship cell). This way, for [l..r] segment the formula should be .

For solving the problem we should store all the [l..r] segments which has no ''free'' cells (none of them was shooted). One could use (std: : set) for that purpose. This way, before the shooting, there will be only one segment [1..n]. Also we will store current maximum number of ships we could place on a board. Before the shooting it is equal to .

With every shoot in cell x we should find the segment containing shooted cell (let it be [l..r]), we should update segment set. First, we should delete [l..r] segment. It means we should decrease current maximum number of ships by  and delete it from the set. Next, we need to add segments [l..x - 1] and [x + 1..r] to the set (they may not be correct, so you may need to add only one segments or do not add segments at all) and update the maximum number of ships properly. We should process shoots one by one, and when the maximum number of ships will become lesser than k, we must output the answer. If that never happen, output  - 1.

AC代码:

#include <iostream>
#include <cstdio>
#include <set>
using namespace std;

set<int> s;

int main(){
    int n,k,a,m;
    while(~scanf("%d%d%d",&n,&k,&a)){
        scanf("%d",&m);
        s.clear();
        s.insert(0);
        s.insert(n+1);
        int ans = (n+1)/(a+1);
        int ans_id = -1;
        for(int i = 1; i <= m; i++){
            int x;
            scanf("%d",&x);
            if(ans < k)
                continue;
            s.insert(x);
            set<int>::iterator it = s.find(x);
            int l = *(--it);
            int r = *(++(++it));
            ans -= (r-l)/(a+1);
            ans += (x-l)/(a+1) + (r-x)/(a+1);
            if(ans < k)
                ans_id = i;
        }
        printf("%d\n",ans_id);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值