zoukankan      html  css  js  c++  java
  • codeforces 567D.One-Dimensional Battle Ships 解题报告

    题目链接:http://codeforces.com/problemset/problem/567/D

    题目意思:给出 1 * n 的 field,编号从左至右依次为 1,2,...,n。问射 m 枪之后(第 i 次射中编号 xi,则 xi 这一点是不能放置船只的!),能不能将 k 只 1 * a 的小船放到这些没有经过被射中编号的 field 中 。由于Alice 每次 shoot 的时候都会说 miss 的,即没有打中,你需要判断第几次shoot 使得整个field 不能放置 k 只 小船,如果都能放,最终输出 - 1.

      首先,外国人的题解真是好严谨,又好体~~~

      有几点需要解释下。事实上这几点也困惑了我好久 0.0

      (1)一开始整个区间 (n+1)/(a+1) 可能好多人还是不太明白。那么列条方程帮助理解吧。假设在[1, n] 中最多可以放置 x 只船,可以列出 x * a + (x - 1) = n,于是经若干合并同类项,就可以得到 x =  (n+1)/(a+1)。或者可以按题解者那样理解,由于最大放船数肯定是从最边边开始放的啦,然后间隔一个shoot之后随之放入另一只船。。。很容易知道,每只船占的空间至少为a+1(最尾那只可能不止又或者是a(可喜可贺啊)),那么我们可以虚拟多一个编号为 n+1 的 field。所以整个长度就为 (n+1)/ (a+1)了,很神奇哇~

      (2)(r-l+2)/(a+1) 是啥来的?!如果理解了第一点就很容易明白了。我们shoot完之后,这个 shoot 将空间一分为二了,选定的空间我们用集合set 的 upper_bound来找,返回的是 r ,前一个就是  l 。r-l+1很容易理解(不理解可以私聊我),再+1 就是虚拟的那个field。第(1)点已经说了,紧挨着边放置是最优解的条件!最后记得把shoot这个编号放入下一轮备选空间上。

      (3)空间中为什么要减完再加。因为有个shoot将空间一分为二嘛~~这个时候可以放置的船已经不是原来的[l, r] 这么多了。而是被分开的左区间[l, x-1] 和 [x+1, r] 之和这么多。

      

     1 #include <iostream>
     2 #include <cstring>
     3 #include <cstdio>
     4 #include <algorithm>
     5 #include <set>
     6 using namespace std;
     7 
     8 set<int> s;
     9 
    10 int main()
    11 {
    12     #ifndef ONLINE_JUDGE
    13         freopen("in.txt", "r", stdin);
    14     #endif // ONLINE_JUDGE
    15 
    16     int m, n, a, k, x;
    17     while (scanf("%d%d%d", &n, &k, &a) != EOF) {
    18         scanf("%d", &m);
    19         s.clear();
    20         s.insert(0), s.insert(n+1);   // 实现虚拟长度的小技巧
    21         int sum = (n+1) / (a+1); 
    22         int ans = -1, f = 0;
    23         for (int i = 1; i <= m; i++) {
    24             scanf("%d", &x);
    25             set<int>::iterator it = s.upper_bound(x);
    26             int r = *it;
    27             int l = *(--it);
    28             sum = sum - (r-l)/(a+1) +(x-l)/(a+1) + (r-x)/(a+1);
    29 
    30             if (sum < k && !f) {
    31                 ans = i;
    32                 f = 1;
    33             }
    34             s.insert(x);
    35         }
    36         printf("%d
    ", ans);
    37     }
    38     return 0;
    39 }

      

      

  • 相关阅读:
    mysql 中将汉字(中文)按照拼音首字母排序
    数据库连接客户端 dbeaver 程序包以及使用说明
    maven 项目在 tomcat 中启动报错:Caused by: java.util.zip.ZipException: invalid LOC header (bad signature)
    iPadOS 更新日志
    iOS 更新日志
    mybatis 中 if else 用法
    Chrome 地址栏如何设置显示 http/https 和 www
    Windows 常用工具 & 开发工具 & Chrome插件 & Firefox 插件 & 办公软件
    elasticsearch安装ik分词器
    js关闭浏览器
  • 原文地址:https://www.cnblogs.com/windysai/p/4714806.html
Copyright © 2011-2022 走看看