经历越多,越会发现,很多事情的解决并不是唯一的,一个问题的解决方案往往有很多种,也越来越发现单一的思想适应不了这个时代,几乎没有什么事情是非黑即白这么绝对的,人也是如此。
对于背包问题也是如此,下面就贪心算法和动态规划两种方式进行比较,同时加深一下认识这两种思想的区别。
贪心算法
贪心算法是一种在每一步选择中都采取当前状态下最优决策的算法。它通常用于解决最优化问题,每一步的选择都是局部最优的,但不一定能得到全局最优解。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
double knapsackGreedy(vector<int> values, vector<int> weights, int capacity) {
int n = values.size();
vector<pair<double, int>> valuePerWeight(n);
for (int i = 0; i < n; i++) {
//以单位价值和索引作为一对数据存储起来
valuePerWeight[i] = make_pair((double)values[i] / weights[i], i);
}
sort(valuePerWeight.rbegin(), valuePerWeight.rend());
double totalValue = 0;
int remainingCapacity = capacity;
//auto自动确定vw的数据类型,vw是valuePerWeight的一个迭代器
for (auto vw : valuePerWeight) {
//second用来获取索引的值,
int i = vw.second;
if (weights[i] <= remainingCapacity) {
totalValue += values[i];
remainingCapacity -= weights[i];
} else {
totalValue += vw.first * remainingCapacity;
break;
}
}
return totalValue;
}
int main() {
vector<int> values = {60, 100, 120};
vector<int> weights = {10, 20, 30};
int capacity = 50;
cout << knapsackGreedy(values, weights, capacity) << endl;
return 0;
}
动态规划
动态规划是一种通过把原问题分解为相对简单的子问题的方式来解决复杂问题的方法。通过存储子问题的解,避免重复计算,动态规划能够有效地解决一些具有重叠子问题和最优子结构性质的问题,如背包问题、最长递增子序列等。
#include <iostream>
#include <vector>
using namespace std;
int knapsackDP(vector<int> values, vector<int> weights, int capacity) {
int n = values.size();
//利用vector容器创建一个n行capacity列的二维数组
vector<vector<int>> dp(n + 1, vector<int>(capacity + 1, 0));
for (int i = 1; i <= n; i++) {
for (int w = 1; w <= capacity; w++) {
if (weights[i - 1] <= w) {
//执行n*capacity次,并每次都和上一次的结果比较,并保留大的值
dp[i][w] = max(dp[i - 1][w], dp[i - 1][w - weights[i - 1]] + values[i - 1]);
} else {
dp[i][w] = dp[i - 1][w];
}
}
}
//输出最终结果
return dp[n][capacity];
}
int main() {
vector<int> values = {60, 100, 120};
vector<int> weights = {10, 20, 30};
int capacity = 50;
cout << knapsackDP(values, weights, capacity) << endl;
return 0;
}
二者的区别和联系
贪心算法和动态规划都是解决问题的算法思想,它们的区别和联系如下:
1. 区别:
- 贪心算法每一步都选择当前最优解,不考虑之后的结果,局部最优解能够导致全局最优解。动态规划则是通过存储子问题的解,避免重复计算,通过比较不同的选择来得到最优解。
- 贪心算法通常用于解决一些最优化问题,但不能解决所有问题,因为贪心选择可能导致无法得到最优解。动态规划则可以解决更广泛的问题,能够处理更复杂的情况。
2. 联系:
- 贪心算法和动态规划都是通过将原问题分解为子问题来解决问题的方法。
- 在某些情况下,贪心算法和动态规划可以得到相同的最优解,比如某些背包问题。
- 在实际应用中,根据问题的特点选择贪心算法或动态规划来解决问题,有时候也可以结合两者来得到更好的解决方案。