首页 > 贪心:Burst Balloons 最少次数完成射击气球

贪心:Burst Balloons 最少次数完成射击气球

已知在一个平面上有一定数量的气球,平面可以看作一个坐标系,在平面的x轴的不同位 置安排弓箭手向y轴方向射箭,弓箭可以向y轴走无穷远;给定气球的宽度 xstart ≤ x ≤ xend,问至少需要多少弓箭手,将全部气球打爆?

例如: 四个气球 : [[10,16], [2,8], [1,6], [7,12]],至少需要2个弓箭手。

如下过程

在这里插入图片描述

在射击的过程中想要安排最少的弓箭手保证能够完成所有气球的射击任务,我们可以从中寻找到贪心规律

  1. 对于一个气球,至少需要一个弓箭手才能够射穿
  2. 当一个弓箭手射穿一个气球的同时尽可能多得射穿其他的气球,这就是我们想要达到的安排最少弓箭手的方式

可以使用如下迭代策略:

维护一个射击区间,保证在遍历气球的过程中射击区间的左端点是小于右端点;否则就需要增加一个弓箭手,同时再维护一个新的射击区间。

算法实现如下:

/*
贪心规律:
维护一个射击区间,且该射击区间不断缩小,直到容纳最多的气球
*/
int get_least_shooter(vector<pair<int,int>> &bollon) { if (bollon.size() < 2) { return bollon.size();}int shooter = 1;/*排序的目的是为了保证气球的起始值从小到大,随着遍历的进行,气球的起始值逐渐增大*/sort(bollon.begin(),bollon.end(),cmp);int begin = bollon[0].first;//射击区间的左边界int end = bollon[0].second;//射击区间的右边界for (int i = 0;i < bollon.size(); ++i) { if (end >= bollon[i].first) {  //当左边界大于右边界时停止维护射击区间begin = bollon[i].first;if (end > bollon[i].second) { //不断缩小右边界的范围end = bollon[i].second;}} else{ shooter++;begin = bollon[i].first;end = bollon[i].second;}}return shooter;
}

测试代码如下:

#include 
#include 
#include using namespace std;bool cmp(pair<int,int> a,pair<int,int> b) { return a.first < b.first;
}int get_least_shooter(vector<pair<int,int>> &bollon) { if (bollon.size() < 2) { return bollon.size();}int shooter = 1;sort(bollon.begin(),bollon.end(),cmp);int begin = bollon[0].first;int end = bollon[0].second;for (int i = 0;i < bollon.size(); ++i) { if (end >= bollon[i].first) { begin = bollon[i].first;if (end > bollon[i].second) { end = bollon[i].second;}} else{ shooter++;begin = bollon[i].first;end = bollon[i].second;}}return shooter;
}int main(){ vector<pair<int,int>> bollon;pair<int,int> a;cout <<"constuct the bollon " << endl;for (int i = 0;i < 5; ++i) { cin >> a.first;cin >> a.second;bollon.push_back(a);}cout << "the least of the shootors is " << get_least_shooter(bollon);return 0;
}

输出结果如下

constuct the bollon 
10 16
2 8
1 6
7 12
20 21
the least of the shootors is 3

更多相关:

  •         Apache POI是一个开源的利用Java读写Excel,WORD等微软OLE2组件文档的项目。        我的需求是对Excel的数据进行导入或将数据以Excel的形式导出。先上简单的测试代码:package com.xing.studyTest.poi;import java.io.FileInputSt...

  • 要取得[a,b)的随机整数,使用(rand() % (b-a))+ a; 要取得[a,b]的随机整数,使用(rand() % (b-a+1))+ a; 要取得(a,b]的随机整数,使用(rand() % (b-a))+ a + 1; 通用公式:a + rand() % n;其中的a是起始值,n是整数的范围。 要取得a到b之间的...

  • 利用本征图像分解(Intrinsic Image Decomposition)算法,将图像分解为shading(illumination) image 和 reflectance(albedo) image,计算图像的reflectance image。 Reflectance Image 是指在变化的光照条件下能够维持不变的图像部分...

  • 题目:面试题39. 数组中出现次数超过一半的数字 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。 你可以假设数组是非空的,并且给定的数组总是存在多数元素。 示例 1: 输入: [1, 2, 3, 2, 2, 2, 5, 4, 2] 输出: 2 限制: 1 <= 数组长度 <= 50000 解题: cl...

  • 题目:二叉搜索树的后序遍历序列 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 true,否则返回 false。假设输入的数组的任意两个数字都互不相同。 参考以下这颗二叉搜索树:      5     /    2   6   /  1   3示例 1: 输入: [1,6,3,2,5] 输出...

  • 在二维空间中有许多球形的气球。对于每个气球,提供的输入是水平方向上,气球直径的开始和结束坐标。由于它是水平的,所以y坐标并不重要,因此只要知道开始和结束的x坐标就足够了。开始坐标总是小于结束坐标。平面内最多存在104个气球。 一支弓箭可以沿着x轴从不同点完全垂直地射出。在坐标x处射出一支箭,若有一个气球的直径的开始和结束坐标为 xs...