0
点赞
收藏
分享

微信扫一扫

贪心——思想及编码实践



1,简单贪心

作用:求解一类最优化问题的方法

特点:总考虑在当前状态下局部最优(或较优)的策略


严谨使用贪心算法求解最优化问题需要对采取的策略进行证明(反证法以——【假设策略不能导致最优解,最后通过一些列推导来得到矛盾,以此证明策略是最优的】及数学归纳法【最后保证全局最优】)


⚠️:贪心的证明往往比贪心本身更难。因此如果想到某个似乎可行的策略,并且自己无法举出反例,那么就勇敢的去实现它。


2,区间贪心

题目:

给出N个开区间(x,y),从中选择尽可能多的开区间,使得这些开区间两两没有交集。

例如对于开区间(1,3)、(2,4)、(3,5)、(6,7)来说,可以选出最多三个区间(1,3)、(3,5)、(6,7)它们两两没有交集。

参考代码:

#include<cstdio>
#include<algorithm>

using namespace std;

const int manx = 110;
struct Interval{
int x,y;
}itval[manx];

bool cmp(Interval a, Interval b){
if(a.x != b.x) return a.x > b.x;//先按左端点从大到小排序
else return a.y < b.y; //左端点相同,再按有右端点从小到大排序
}

int main(){
int n;
scanf("%d", &n);
for (int i = 0; i < n; ++i) {
scanf("%d%d", &itval[i].x, &itval[i].y);
}
sort(itval, itval + n, cmp);//区间排序

int left = itval[0].x, num = 1;
for (int j = 0; j < n; ++j) { //如果该区间的右端点在left的右边
if(itval[j].y <= left){ //以itval[j]为新选中的区间
left = itval[j].x; //不相交的区间个数加1
num++;
}
}

printf("%d\n", num);
return 0;
}


参考代码2:

#include<cstdio>
#include<algorithm>

using namespace std;

const int manx = 110;
struct Interval{
int x,y;
}itval[manx];

bool cmp(Interval a, Interval b){
if(a.y != b.y) return a.y < b.y;//先按右端点从小到大排序
else return a.x < b.x; //左端点相同,再按有左端点从小到大排序
}

int main(){
int n;
scanf("%d", &n);
for (int i = 0; i < n; ++i) {
scanf("%d%d", &itval[i].x, &itval[i].y);
}
sort(itval, itval + n, cmp);//区间排序

int right = itval[0].y, num = 1;
for (int j = 0; j < n; ++j) { //如果该区间的右端点在left的右边
if(itval[j].x >= right){ //以itval[j]为新选中的区间
right = itval[j].y; //不相交的区间个数加1
num++;
}
}

printf("%d\n", num);
return 0;
}

与上述问题类似的区间选点问题,给出N个闭区间[x,y],求最少需要多少个点,才能使每个区间中都至少存在一个点。

参考代码:

#include<cstdio>
#include<algorithm>

using namespace std;

const int manx = 110;
struct Interval{
int x,y;
}itval[manx];

bool cmp(Interval a, Interval b){
if(a.x != b.x) return a.x > b.x;//先按左端点从大到小排序
else return a.y < b.y; //左端点相同,再按有右端点从小到大排序
}

int main(){
int n;
scanf("%d", &n);
for (int i = 0; i < n; ++i) {
scanf("%d%d", &itval[i].x, &itval[i].y);
}
sort(itval, itval + n, cmp);//区间排序

int left = itval[0].x, num = 1;
for (int j = 0; j < n; ++j) { //如果该区间的右端点在left的右边
if(itval[j].y < left){ //以itval[j]为新选中的区间
left = itval[j].x; //不相交的区间个数加1
num++;
}
}

printf("%d\n", num);
return 0;
}

3,总结

贪心是用来解决一类最优化问题,并希望由局部最优策略来推得全局最优结果的算法。

适用于:一定满足最优子结构性质,即一个问题的最优解可以由其他的子问题的最优解有效构造出来。


举报

相关推荐

0 条评论