贪心算法
贪心算法总是做出最好的选择,期望通过局部最优解得到全局最优的解决方案。从问题的初始题解开始,一步一步的做出当前最优的选择,逐步逼近问题的目标,尽可能得到最优解。即使不是最优解,也可以得到最优解的近似解
贪心算法并不是从整体最优来考虑的,它做出的选择只能是某种意义上的局部最优。
贪心本质
当问题具备两个特性:贪心选择性质 和 最优子结构性质 的时候,这个问题可以使用贪心算法
(1) 贪心选择性质:贪心选择性质指原问题的整体最优解可以通过一系列局部最优解的选择得到。
(2) 最优子结构:当一个问题的最优解包含其值问题的最优解时,称此问题具有最优子结构性质
贪心算法解题步骤:
- 贪心策略:指确定贪心策略,选择当前看上去是最好的一个。例如当选苹果时,当认为苹果最红是最好的,就每次挑选苹果堆中最红的。或者当选苹果的策略变为最大的是最好的,就每次挑选苹果堆中最大的。根据题目的需求,不同的题目有不同的贪心策略
- 局部最优解:指根据贪心策略,一步一步地得到局部最优解。
- 全局最优解:只把所有的局部最优解都结合成一个问题的最优解
最优装载问题
题目简介:
有一天,海盗们截获了一搜装满各种各样古董的货船,每件古董都价值连城,一旦打碎就失去了价值。虽然海盗船足够大,但载重为 c c c ,每件古董的重量为 w i w_i wi ,海盗们要怎么才能实现最大化价值?
1、问题分析
根据问题描述,这是一个贪心算法求解最优解的问题,题目中没有说明每件物品的价值,因此当装载的古董数量最多时,价值最高。而船的容量是固定的,那么装载时从重量最轻的开始,一件一件的装载,使其装的古董数量最多。可以采用重量最轻者先装载的贪心选择策略,从局部最优达到全局最优,从而得到最优装载问题的最优解
2、算法设计
- 当载重为定值 c c c 时,$ w_i$ 越小,可装载的古董数量 n 越大。依次装入重量最小的古董,知道不能载入为止
- 把 n 个古董的重量从小到大排序,然后根据贪心策略尽可能的选出前 i 个古董,直到不能继续装入为止。这时装入的古董数量达到全局最优解
3、算法实现
#include<iostream>
#include<algorithm>
using namespace std;
int main(){
int c;
cout << "输入船的容量:" ;
cin >> c;
int n;
cout << "输入古董数量:";
cin >> n;
int *arr = new int[n];
cout << "请输入各古董的重量:" << endl;
for (int i = 0; i < n; i++){
cin >> arr[i];
}
//对数组进行排序
sort(&arr[0], &arr[n]);
for (int i = 0; i < n; i++){
cout << arr[i] << endl;
}
double temp = 0.0;
int ans = 0;//temp为已经装到船上的古董的重量,ans为已经装载的古董个数
for (int i = 0; i < n; i++){
temp += arr[i];
if (temp <= c){
ans++;
}
else{
break;
}
}
cout << "最多可以装:" << ans << " 件古董" << endl;
return 0;
}
4、算法分析
时间复杂度:按古董重量排序并调用 sort()
函数,其平均时间复杂度为
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn),输入和贪心策略求解的两个for语句的时间复杂度均为
O
(
n
)
O(n)
O(n),因此总时间复杂度为:
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn)
空间复杂度:在程序中使用了 temp、ans等辅助变量,空间复杂度为 O ( 1 ) O(1) O(1)