万恶之源

题意

给定若干个点的坐标,与范围R。每个点可以选择是否标记,标记后这个点的左右范围R内的所有点也会被标记,求为使所有点被标记,我们要主动标记多少个点。

思路

这题总感觉可以用搜索做,毕竟每个点的状态要么是1要么是0。但这是书上贪心的例题,那肯定得用贪心做啦。

贪心的原则是什么呢?

错解

首先我们的目标是尽可能少的标记,因此我们当然可以希望每次一次性标记的点越多越好,那么我们是不是可以遍历每个点,每次选择一次性标记数最多的点来标记呢?显然不行 我们可以看一下这个数据

1 9
1 2 2 3 3 3 4 4 5

显然在这种规则下程序会选择标记3,一口气标记了7个数字呢!然后呢,望不到彼此的1和5只能自己标记自己,因此最后我们主动标记了3个数。显然不是最优解。(其实这就是我的原始想法)

正解

我们可以从最左边开始考虑。在上述例子的条件下,我们肯定不会标记“1”,因为这样会浪费左边的范围,即标记“2”是优于标记“1”的。但是标记“3”就不是最优解了,为什么呢?因为标记“3”覆盖不到“1”,也就是留了个孤零零的元素没标记,这样子我们不得不单独的标记"1"。总而言之,标记“1”会浪费左边的空间,所以我们会试着选择标记“2”以及后面的元素,但是标记“3”不能照顾到”1“,带来了额外的成本,因此我们会选择标记2。所以我们希望被标记的点尽量靠右,不浪费左边的空间,但是也不能不覆盖最左边未标记的元素(即留空子)。

因此,贪心的原则应该是这样。

每次给最左边未标记的点的R范围内,最靠右的点标记。然后不断重复这一过程。

代码实现

书上的代码

int N, R;
int X[MAXN]; void solve(){
sort(X, X + N); int i = 0, ans = 0;
while(i < N){
int s = X[i++];//s是没有被覆盖的最左侧的位置
while(i < N && X[i] <= s + R) i++;
//一直向右前进,直到到达距离s的距离严格大于R的点(此处用的是小于等于号)
//相当于拓展p点的左侧 int p = X[i - 1];//p是新加上标记的点的位置,因为X[i]是接触不到s的
while (i < N && X[i] <= p + R) i++;
//一直向右前进,直到到达距离p的距离严格大于R的点
//相当于拓展p点的右侧 ans++;
}
printf("%d\n", ans);
}

我的代码

int r, n;
int troop[2000];//存储每只队伍的坐标 sort(troop, troop + n);
int tag = 0, ans = 0;////tag是没有被覆盖的最左侧的位置
troop[n] = 0x3f3f3f3f;//哨兵元素
for (int i = 0; i <= n; i++)
{
if (troop[i] - r > troop[tag]) {
ans++;
//标记点+1,没有明说,但标记的是i - 1
while (troop[i - 1] + r >= troop[tag]) tag++;
//更新标记点的右侧,也就是更新标记点的位置
}
//printf("%d---%d---%d\n", troop[i], troop[tag], ans);
}
printf("%d\n", ans);

比较一下

首先二者的思路是一致的。感觉区别在于书上的代码是一股气从左冲到右,而我的是一个一个检查,延迟标记(这也是为什么有一个哨兵的原因)

问题

我的问题主要在于一开始没有设置一个哨兵元素,然后我用很多if语句去判断各种情况来修补bug,但是修修补补终究不能AC。后来意识到标记不是即时的,才设置了一个哨兵元素,结果之前的if语句全部可以删掉,完美AC。可能一开始的方向就很重要吧。

历史提交

参考书籍:《挑战程序设计竞赛》

贪心-Saruman‘s Army POJ - 3069的更多相关文章

  1. Q - Saruman's Army POJ - 3069

    Saruman the White must lead his army along a straight path from Isengard to Helm's Deep. To keep tra ...

  2. Saruman's Army (POJ 3069)

    直线上有N个点.点i的位置是Xi.从这N个点中选择若干个,给它们加上标记.对每一个点,其距离为R以内的区域里必须又带有标记的点(自己本身带有标记的点,可以认为与其距离为0的地方有一个带有标记的点).在 ...

  3. POJ 3617 Best Cow Line ||POJ 3069 Saruman's Army贪心

    带来两题贪心算法的题. 1.给定长度为N的字符串S,要构造一个长度为N的字符串T.起初,T是一个空串,随后反复进行下面两个操作:1.从S的头部删除一个字符,加到T的尾部.2.从S的尾部删除一个字符,加 ...

  4. POJ 3069 Saruman's Army(贪心)

     Saruman's Army Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Sub ...

  5. poj 3069 Saruman's Army(贪心)

    Saruman's Army Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 131072/65536K (Java/Other) Tot ...

  6. poj 3069 Saruman's Army 贪心模拟

    Saruman's Army Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 18794   Accepted: 9222 D ...

  7. POJ 3069 Saruman's Army(萨鲁曼军)

    POJ 3069 Saruman's Army(萨鲁曼军) Time Limit: 1000MS   Memory Limit: 65536K [Description] [题目描述] Saruman ...

  8. poj 3069 Saruman's Army

    Saruman's Army Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8477   Accepted: 4317 De ...

  9. POJ 3069:Saruman's Army

    Saruman's Army Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 13242   Accepted: 6636 D ...

随机推荐

  1. Pikachu靶场通关之XSS(跨站脚本)

    一.XSS(跨站脚本)概述 Cross-Site Scripting 简称为"CSS",为避免与前端叠成样式表的缩写"CSS"冲突,故又称XSS.一般XSS可以 ...

  2. AspectJWeaver文件写入gadget详解和两种应用场景举例

    目录 0 前言 1 环境 2 gadget解析 2.1 高版本Commons-Collections的防御措施 2.2 获取AspectJWeaver的调用链 2.3 gadget详解 3 两种应用场 ...

  3. axios与vue-resource

    在Vue项目中前后端交互时,早期Vue使用Vue-resource实现异步请求.从Vue2.0之后就不再对vue-resource进行更新,Vue官方推荐使用axios. vue-resource V ...

  4. 记一次k8s pod频繁重启的优化之旅

    关键词:k8s.jvm.高可用 1.背景 最近有运维反馈某个微服务频繁重启,客户映像特别不好,需要我们尽快看一下. 听他说完我立马到监控平台去看这个服务的运行情况,确实重启了很多次.对于技术人员来说, ...

  5. 记一次 .NET 某上市工业智造 CPU+内存+挂死 三高分析

    一:背景 1. 讲故事 上个月有位朋友加wx告知他的程序有挂死现象,询问如何进一步分析,截图如下: 看这位朋友还是有一定的分析基础,可能玩的少,缺乏一定的分析经验,当我简单分析之后,我发现这个dump ...

  6. Shell系列(19)- 正则表达式

    正则表达式与通配符 正则表达式用来在文件中匹配符合条件的字符串,正则是包含匹配.grep,awk,sed等命令可以支持正则表达式. 通配符用来匹配符号条件的文件名,通配符是完全匹配.ls,find,c ...

  7. Windows 10 64位操作系统 下安装、连接测试sqlite3 sql基本操作 增删改

    一.下载sqlite安装包 1:详细下载安装版本可见官网:https://www.sqlite.org/download.html 2:百度盘分享连接:https://pan.baidu.com/s/ ...

  8. P3971-[TJOI2014]Alice and Bob【贪心】

    正题 题目链接:https://www.luogu.com.cn/problem/P3971 题目大意 一个\(1\sim n\)的一个排列,设\(a_i\)表示以\(i\)结尾的最长上升子序列长度, ...

  9. sonar入门

    一.Sonar是什么? 根据我的了解,可以说Sonar包含三个部分: SonarQube是一种自动代码审查工具,用于检测代码中的错误,漏洞和代码味道.它可以与您现有的工作流程集成,以实现跨项目分支和提 ...

  10. 如何基于Security实现OIDC单点登录?

    一.说明 本文主要是给大家介绍 OIDC 的核心概念以及如何通过对 Spring Security 的授权码模式进行扩展来实现 OIDC 的单点登录. OIDC 是 OpenID Connect 的简 ...