贪心法——选择不相交区间
选择不相交区间。数轴上有 n 个开区间
(ai,bi) 。选择尽量多个区间,使得这些区间两两没有公共点。
贪心思路:按 b <script id="MathJax-Element-703" type="math/tex">b</script>的大小,将区间从小到大排序,选择最小的区间,再选择和该区间无交点的最小区间,以此往复,知道遍历完所有区间。
选择不相交区间算法实现
// 区间数据结构
struct Region {
// 左区间
int left;
// 右区间
int right;
operator < (const Region &r) {
return right < r.right;
}
};
// 贪心法
// 选择不相交区间
void region(Region *r, int n) {
// 按右区间大小从小到大排序
sort(r, r + n);
// 最小右区间
int minRight = r[0].right;
cout << "区间为:(" << r[0].left << "," << r[0].right << ")" << endl;
// 区间总数
int sumRegion = 0;
for(int i = 1; i < n; i++) {
if(r[i].left >= minRight) {
cout << "区间为:(" << r[i].left << "," << r[i].right << ")" << endl;
minRight = r[i].right;
}
}
}
测试主程序
#include <iostream>
#include <algorithm>
using namespace std;
// 区间数据结构
struct Region {
// 左区间
int left;
// 右区间
int right;
operator < (const Region &r) {
return right < r.right;
}
};
// 贪心法
// 选择不相交区间
void region(Region *r, int n) {
// 按右区间大小从小到大排序
sort(r, r + n);
// 最小右区间
int minRight = r[0].right;
cout << "区间为:(" << r[0].left << "," << r[0].right << ")" << endl;
// 区间总数
int sumRegion = 0;
for(int i = 1; i < n; i++) {
if(r[i].left >= minRight) {
cout << "区间为:(" << r[i].left << "," << r[i].right << ")" << endl;
minRight = r[i].right;
}
}
}
int main() {
while(true) {
// n个开区间
int n;
cout << "请输入开区间的数量(0退出):";
cin >> n;
if(!n) {
break;
}
Region r[n];
for(int i = 0; i < n; i++) {
cout << "第" << i + 1 << "个开区间(x,y)为:";
cin >> r[i].left;
cin >> r[i].right;
}
cout << "最大不相交开区间组合和总数为:" << endl;
region(r, n);
}
return 0;
}
输出数据
请输入开区间的数量(0退出):5
第1个开区间(x,y)为:1 2
第2个开区间(x,y)为:2 3
第3个开区间(x,y)为:1 3
第4个开区间(x,y)为:3 5
第5个开区间(x,y)为:4 5
最大不相交开区间组合和总数为:
区间为:(1,2)
区间为:(2,3)
区间为:(3,5)
请输入开区间的数量(0退出):10
第1个开区间(x,y)为:1 3
第2个开区间(x,y)为:2 3
第3个开区间(x,y)为:5 6
第4个开区间(x,y)为:4 7
第5个开区间(x,y)为:3 8
第6个开区间(x,y)为:3 6
第7个开区间(x,y)为:6 8
第8个开区间(x,y)为:7 9
第9个开区间(x,y)为:10 11
第10个开区间(x,y)为:11 12
最大不相交开区间组合和总数为:
区间为:(1,3)
区间为:(5,6)
区间为:(6,8)
区间为:(10,11)
区间为:(11,12)
请输入开区间的数量(0退出):0
Process returned 0 (0x0) execution time : 73.788 s
Press any key to continue.