贪心算法----区间选点问题(POJ1201)
题目:

题目的大致意思是,给定n个闭区间,并且这个闭区间上的点都是整数,现在要求你使用最少的点来覆盖这些区间并且每个区间的覆盖的点的数量满足输入的要求点覆盖区间的数量。
输入:
第一行输入n,代表n个区间。
接下来的n行每行的第一个数代表区间起点,第二个数代表区间终点,第三个数代表这个区间必须要选取的点的数量。
输出:
输出最少的点的数量,这些最少的点要覆盖全部区间。
这个题是区间选点问题的一种变体,但是我们对于区间选点问题清楚之后那么这种题目也是一样解决的,只不过需要在某些地方特别处理一下。这道题目跟区间调度的问题非常类似,我们也可以采用区间调度问题的策略运用到这道题目上面,尽量往结束时间的端点来选点因为这样做我们可以使尽量少的点覆盖更多的区间,之后就是选点的问题了,当我们选择了这个点之后需要标记一下,定义一个数轴来记录其中标记过的点,以防下一次在选点的时候重复选择。而且在for循环中依次扫描这些给定的区间,看这个区间需要覆盖的点的数量是多少(有可能这个区间的标记的点出现在另外的区间上那么这个时候我们就选择跳过这个点)
代码:
import java.util.Arrays;
import java.util.Scanner; public class 区间选点问题1 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
Interval[] intervals = new Interval[n];
for (int i = 0; i < n; i++) {
intervals[i] = new Interval(sc.nextInt(), sc.nextInt(), sc.nextInt());
}
Arrays.sort(intervals);// 按区间右端点排序 int max = intervals[n - 1].t;// 右端最大值
int[] axis = new int[max + 1];// 标记数轴上的点是否已经被选中
// int[] sums = new int[max + 1];
for (int i = 0; i < n; i++) {
// 1.查阅区间中有多少个点
int s = intervals[i].s;// 起点
int t = intervals[i].t;// 终点
int cnt = sum(axis, s, t);// 找到这个区间已经选点的数量,
//sums[t] - sums[s - 1]; 效率低
// 2.如果不够,从区间右端开始标记,遇标记过的就跳过
intervals[i].c -= cnt;// 需要新增的点的数量
while (intervals[i].c > 0) {
if (axis[t] == 0) {// 从区间终点开始选点
axis[t] = 1;
// updateSums(t,sums);//更新前缀和
intervals[i].c--;// 进一步减少需要新增的点的数量
t--;
} else {// 这个点已经被选过了
t--;
}
} }
System.out.println(sum(axis, 0, max));
} /**
* 统计数轴axis上s-t区间已经有多少个点被选中
*
* @param axis
* @param s
* @param t
* @return
*/
private static int sum(int[] axis, int s, int t) {
int sum = 0;
for (int i = s; i <= t; i++) {
sum += axis[i];
}
return sum;
} private static void updateSums(int t, int[] sums) {
for (int i = t; i < sums.length; i++) {
sums[i]++;
}
} private static class Interval implements Comparable<Interval> {
int s;
int t;
int c; public Interval(int s, int t, int c) {
this.s = s;
this.t = t;
this.c = c;
} @Override
public int compareTo(Interval other) {
int x = this.t - other.t;
if (x == 0)
return this.s - other.s;
else
return x;
}
}
}
结果:

但是上面这个代码提交到OJ上面会发生超时,代码逻辑本身没有什么问题,关键是在扫描每个区间的时候消耗的时间比较多导致了超时,但是我们可以使用另外的一种数据结构来解决,那就是树状数组,降低扫描区间的时间复杂度。关于树状数组现在不太懂,而且也脱离了贪心算法的范畴,现在把代码记录下来,留作以后再看。
代码:
import java.util.Arrays;
import java.util.Scanner; public class 区间选点问题2 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
Interval[] intervals = new Interval[n];
for (int i = 0; i < n; i++) {
intervals[i] = new Interval(sc.nextInt(), sc.nextInt(), sc.nextInt());
}
Arrays.sort(intervals);// 按区间右端点排序 int max = intervals[n - 1].t;// 右端最大值
int[] axis = new int[max + 1];
int[] c = new int[max + 2];
// int[] sums = new int[max + 1];
for (int i = 0; i < n; i++) {
// 1.查阅区间中有多少个点
int s = intervals[i].s;// 起点
int t = intervals[i].t;// 终点
int cnt = sum(t + 1, c, max + 1) - sum(s, c, max + 1);// sum(axis,s,t);//sums[t]
// - sums[s
// -
// 1];//效率低
// 2.如果不够,从区间右端开始标记,遇标记过的就跳过
intervals[i].c -= cnt;
while (intervals[i].c > 0) {
if (axis[t] == 0) {
axis[t] = 1;
update(t + 1, 1, c, max + 1);
intervals[i].c--;
t--;
} else {
t--;
}
} }
System.out.println(sum(max + 2, c, max + 1));
} /**
* 更新树状数组c,注意i是项数,不是下标,而是下标+1
*/
private static void update(int i, int delta, int[] c, int n) {
for (; i <= n; i += lowbit(i)) {
c[i] += delta;
}
} /**
* 前i项和,注意:i不是下标
*
* @param i
* @return
*/
private static int sum(int i, int[] c, int n) {
int sum = 0;
if (i > n)
i = n;
for (; i > 0; i -= lowbit(i)) {
sum += c[i];
}
return sum;
} /**
* 它通过公式来得出k,其中k就是该值从末尾开始1的位置。 然后将其得出的结果加上x自身就可以得出当前节点的父亲节点的位置
* 或者是x减去其结果就可以得出上一个父亲节点的位置。
* 比如当前是6,二进制就是0110,k为2,那么6+2=8,C(8)则是C(6)的父亲节点的位置;
* 相反,6-2=4,则是C(6)的上一个父亲节点的位置。
*/
static int lowbit(int x) {
return x - (x & (x - 1));
} private static class Interval implements Comparable<Interval> {
int s;
int t;
int c; public Interval(int s, int t, int c) {
this.s = s;
this.t = t;
this.c = c;
} @Override
public int compareTo(Interval other) {
int x = this.t - other.t;
if (x == 0)
return this.s - other.s;
else
return x;
}
}
}
贪心算法----区间选点问题(POJ1201)的更多相关文章
- UVa 1615 Highway (贪心,区间选点问题)
题意:给定一个数 n 个点,和一个d,要求在x轴上选出尽量少的点,使得对于给定的每个点,都有一个选出的点离它的欧几里德距离不超过d. 析:首先这是一个贪心的题目,并且是区间选点问题,什么是区间选点呢, ...
- UVA-1615 Highway (贪心,区间选点)
题目大意:有一条沿x轴正方向,长为L的高速公路,n个村庄,要求修建最少的公路出口数目,使得每个村庄到出口的距离不大于D. 题目分析:区间选点问题.在x轴上,到每个村庄距离为D的点有两个(超出范围除外) ...
- 贪心算法----区间覆盖问题(POJ2376)
题目: 题目的大概意思是约翰这个农民有N条牛,这些牛可以在一天中的某个时间段可以进行工作,他想把这个时间段分成若干个片段让这些牛去进行打扫任务,你的任务是安排尽量少的牛然后可以完成分成这些片段的打扫任 ...
- POJ1328 Radar Installation 【贪心·区间选点】
Radar Installation Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 54593 Accepted: 12 ...
- 【uva 1615】Highway(算法效率--贪心 区间选点问题)
题意:给定平面上N个点和一个值D,要求在x轴上选出尽量少的点,使得对于给定的每个店,都有一个选出的点离它的欧几里德距离不超过D. 解法:先把问题转换成模型,把对平面的点满足条件的点在x轴的直线上可得到 ...
- 基于贪心算法的几类区间覆盖问题 nyoj 12喷水装置(二) nyoj 14会场安排问题
1)区间完全覆盖问题 问题描述:给定一个长度为m的区间,再给出n条线段的起点和终点(注意这里是闭区间),求最少使用多少条线段可以将整个区间完全覆盖 样例: 区间长度8,可选的覆盖线段[2,6],[1, ...
- 【贪心算法】POJ-1328 区间问题
一.题目 Description Assume the coasting is an infinite straight line. Land is in one side of coasting, ...
- POJ 1328 Radar Installation 【贪心 区间选点】
解题思路:给出n个岛屿,n个岛屿的坐标分别为(a1,b1),(a2,b2)-----(an,bn),雷达的覆盖半径为r 求所有的岛屿都被覆盖所需要的最少的雷达数目. 首先将岛屿坐标进行处理,因为雷达的 ...
- 【贪心算法】POJ-2376 区间问题
一.题目 Description Farmer John is assigning some of his N (1 <= N <= 25,000) cows to do some cle ...
随机推荐
- spring MVC 项目 WEB-INF下的jsp不能加载css文件
一.项目目录 二.解决方法(已解决) 1. jsp文件加入 <link href="<c:url value="/css/main.css" />&qu ...
- spring 报错
一. java.lang.ClassNotFoundException: org.springframework.web.filter.CharacterEncodingFilter 解决方案: 1. ...
- SpringBoot 动态切换多数据源
1. 配置文件application-dev.properties 2. 动态切换数据源核心 A. 数据源注册器 B. 动态数据源适配器 C. 自定义注解 D. 动态数据源切面 E. 数据源路 ...
- cmake简明使用指南
cmake简明使用指南 Last update 2018/8/8 先执行cmake生成makefile,然后看看里面的内容,(至少在ubuntu16.04上的cmake3.5.1上),有如下内容提供: ...
- SQL SERVER 2012更改默认的端口号为1772
打开开始菜单,找到sqlserver的配置管理器,点击打开 按下图配置右边窗口三项: 按下图配置右边三项: 按下图配置右边三项: 点击下图左边的SQL Server网络配置/MSSQLSERVER的协 ...
- java思维导图
https://www.edrawsoft.cn/viewer/public/s/eeca7704686971
- ubuntu更换pip install,apt-get,conda install 成国内源
解决ubuntu的pip和apt-get太慢的问题 ubuntu国外龟速的源实在难受,还是自己动手更改一下各种pip 源和apt-get 的源吧,换了之后速度令人舒适! 更换pip源成清华源 临时使用 ...
- C# Levenshtein计算字符串的相似度
static void Main(string[] args) { Levenshtein(@"今天天气不错", @"今天的天气不错啊"); Console.R ...
- Fullcalendar改版后发布到IIS或者tomcat里面前端加载数据不显示的问题
问题如题:Fullcalendar改版后发布到IIS或者tomcat里面前端加载数据不显示的问题 解决办法:通过火狐浏览器工具发现是时间格式不对的原因,需要将时间格式修改为:yyyy-MM--DD ...
- 关于spring aop Advisor排序问题
关于spring aop Advisor排序问题 当我们使用多个Advisor的时候有时候需要排序,这时候可以用注解org.springframework.core.annotation.Order或 ...