14天阅读挑战赛
参考 《趣学算法》 陈小玉教授
(入门书籍,对新手很友好,带你走进算法的大门
学习算法之前 : 雄心壮志
现在:
所以学习算法到底需要不需要天赋呢? 学习算法很吃力,很绝望 怎么办呢?
好了进入正题
贪心策略
- 一、什么是贪心策略
- 二、注意事项
- 三、遵循的原则
- 三、海盗装古董问题
一、什么是贪心策略
正如起名,贪心,很贪。
好比我喜欢睡觉,而且特别喜欢,以至于上课我也睡觉,每天都是白日梦。
又好似我喜欢打游戏,做梦都打游戏。
一个贪心算法总是做出当前最好的选择,也就是说,它期望通过局部最优选择得到全局最优的解决方案。 --《算法导论》
二、注意事项
- 一旦做出选择,就不可以回溯。
- 有可能得不到最优解,而是得到最优解的近似解。
- 选择什么样子的贪心策略直接决定算法的好坏。
三、遵循的原则
有时候,人们无法分清那些问题可以用贪心算法,哪些问题不可以使用。贪心选择,最优子结构 满足这两个性质,就可以使用贪心算法。
1、贪心选择:
2、最优子结构:
理论课结束,让我们开始上机操作吧。
三、海盗装古董问题
问题描述:
海盗截获了一艘装满各种各样古董的货船,每一件值很多 “马内”(金钱),但是打碎了,就一文不值。
海盗船虽然很大,但是载重量有限。
其中一个名叫 “张三” 的海盗说了:我们要尽可能的把古董搬上船,越多越好。
(现在海盗需要你的帮助,我的朋友。)
问题梳理:
1) 问题是怎么装越多越好,我们最在意的是什么呢? -- 是“个数”
2) 利用贪心算法:
我们就挑着重量轻的装,这样我们才能最大的程度上保证个数最多。
程序示例:
#include <iostream>
#include <algorithm>
using namespace std;
//古董
struct Role
{
double num; //重量
char name; //名称
};
//定义排序规则
bool cmp(Role a,Role b)
{
if(a.num < b.num) //从小到大排序
return a.num < b.num;
return a.name > b.name; //如果重量相等,则按照名称排序。
}
int main()
{
int size; //古董的个数
//输入古董的个数
cout<<"古董的个数:"<<endl;
cin>>size;
struct Role r[size]; //保存古董。
double n = 0.0; //海盗船的重量
double temp = 0.0; //已经装入海盗船的重量
int size2= size; //已经装入海盗船的个数
char name2[10]; //已装入海盗船古董的名称
//输入古董的名称、重量、价值
int i = 0;
while(i<size)
{
cout<<"请输入("<<i+1<<")古董名称、重量"<<endl;
cin>>r[i].name>>r[i].num;
i++;
}
//输入海盗船的装量
cout<<"请输入海盗船的重量:"<<endl;
cin>>n;
//因为我们采用的是贪心策略,对重量进行排序,按照从轻到重。
sort(r,r+size,cmp); //升序排列(从轻到重)
for(int i=0;i<size;i++)
{
temp += r[i].num; //海盗船的重量增加
if(temp >= n) //超重
{
if(temp > n) //如果超重或等于船的载重
{
size2 = i; //装入海盗船的古董个数
}else
{
size2 = i+1; //如果没有超重,则 海盗成功盗走一件.
name2[i] = r[i].name; //装入海盗床的古董名称。
}
break;
}
name2[i] = r[i].name; //装入海盗船的古董名称。
}
cout<<"海盗盗走的古董名称:"<<endl;
//遍历
for(int i = 0;i<size2;i++)
cout<<name2[i]<<endl;
return 0;
}
运行结果: