算法c++实验分析 1、<验证> 输入背包容量,物品数量、价值及重量,利用动态规划法解决0-1背包问题,要求输出装入物品的对应指示向量,并分析该算法性能。 2、<探索> 当背包允许物品部分装入时,重新设计动态规划策略,满足背包承载最大时价值最高,输出指示向量,并与问题1结果相比较,同时分析算法性能差异。
时间: 2024-03-04 07:53:36 浏览: 69
对于问题1,动态规划解决0-1背包问题的时间复杂度为O(nW),其中n为物品数量,W为背包容量。具体实现过程中,可以使用一个二维数组dp[i][j]表示在前i件物品中选择一些物品放入容量为j的背包中所能获得的最大价值。根据动态转移方程dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]]+v[i]),可以求解出最大价值。最后倒序遍历dp数组确定放入背包的物品。
对于问题2,可以将0-1背包问题转换成部分背包问题。具体实现过程中,可以使用一个一维数组dp[j]表示在容量为j的背包中所能获得的最大价值。根据动态转移方程dp[j] = max(dp[j], dp[j-w[i]]+v[i]),可以求解出最大价值。同时,记录下放入背包的物品数量和对应的价值,即可输出指示向量。
相比于问题1,问题2的时间复杂度为O(nW),空间复杂度为O(W)。可以看出,问题2在时间和空间上都优于问题1。
相关问题
编写算法c++程序实现: 1、<验证> 输入背包容量,物品数量、价值及重量,利用动态规划法解决0-1背包问题,要求输出装入物品的对应指示向量,并分析该算法性能。 2、<探索> 当背包允许物品部分装入时,重新设计动态规划策略,满足背包承载最大时价值最高,输出指示向量,并与问题1结果相比较,同时分析算法性能差异。
好的,以下是C++代码实现:
问题1:
```cpp
#include<iostream>
#include<vector>
using namespace std;
void knapsack_01(int capacity, vector<int>& weights, vector<int>& values, int n) {
vector<vector<int>> K(n + 1, vector<int>(capacity + 1, 0));
for (int i = 0; i <= n; i++) {
for (int w = 0; w <= capacity; w++) {
if (i == 0 || w == 0)
K[i][w] = 0;
else if (weights[i - 1] <= w)
K[i][w] = max(values[i - 1] + K[i - 1][w - weights[i - 1]], K[i - 1][w]);
else
K[i][w] = K[i - 1][w];
}
}
int res = K[n][capacity];
cout << "最大价值为:" << res << endl;
int w = capacity;
for (int i = n; i > 0 && res > 0; i--) {
if (res == K[i - 1][w])
continue;
else {
cout << "选择物品" << i << endl;
res -= values[i - 1];
w -= weights[i - 1];
}
}
}
int main() {
int capacity = 50;
vector<int> weights = { 10, 20, 30 };
vector<int> values = { 60, 100, 120 };
int n = weights.size();
knapsack_01(capacity, weights, values, n);
return 0;
}
```
问题2:
```cpp
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
struct Item {
int weight;
int value;
double ratio;
};
bool cmp(Item a, Item b) {
return a.ratio > b.ratio;
}
void fractional_knapsack(int capacity, vector<int>& weights, vector<int>& values, int n) {
vector<Item> items(n);
for (int i = 0; i < n; i++) {
items[i].weight = weights[i];
items[i].value = values[i];
items[i].ratio = (double)values[i] / weights[i];
}
sort(items.begin(), items.end(), cmp);
int current_weight = 0;
int current_value = 0;
for (int i = 0; i < n; i++) {
if (current_weight + items[i].weight <= capacity) {
current_weight += items[i].weight;
current_value += items[i].value;
cout << "选择物品" << i + 1 << "全部装入" << endl;
}
else {
int remaining_capacity = capacity - current_weight;
double value_per_weight = (double)items[i].value / items[i].weight;
double fraction = (double)remaining_capacity / items[i].weight;
current_weight += remaining_capacity;
current_value += fraction * items[i].value;
cout << "选择物品" << i + 1 << "装入部分,装入比例为" << fraction << endl;
}
}
cout << "总价值为:" << current_value << endl;
}
int main() {
int capacity = 50;
vector<int> weights = { 10, 20, 30 };
vector<int> values = { 60, 100, 120 };
int n = weights.size();
fractional_knapsack(capacity, weights, values, n);
return 0;
}
```
以上代码中,`knapsack_01`函数和`fractional_knapsack`函数分别实现了问题1和问题2的动态规划算法。其中,`knapsack_01`函数的输入参数为背包容量、物品重量列表、物品价值列表和物品数量;`fractional_knapsack`函数的输入参数与之相同。两个函数均输出装入物品的对应指示向量和最大价值(或总价值)。
编写C++程序实现: 1、<验证> 输入背包容量,物品数量、价值及重量,利用动态规划法解决0-1背包问题,要求输出装入物品的对应指示向量,并分析该算法性能。 2、<探索> 当背包允许物品部分装入时,重新设计动态规划策略,满足背包承载最大时价值最高,输出指示向量,并与问题1结果相比较,同时分析算法性能差异。
好的,我理解了你的要求,我将分别回答你的两个问题。
1. C++程序实现0-1背包问题的动态规划算法
0-1背包问题是一种经典的优化问题,其思想是在给定的物品中选择一些物品,使得它们的总价值最大,同时不超过背包的容量限制。这个问题可以通过动态规划求解,具体实现如下:
```cpp
#include <iostream>
#include <vector>
using namespace std;
// 0-1背包问题的动态规划算法
void knapsack01(int C, vector<int> w, vector<int> v)
{
int n = w.size();
vector<vector<int>> dp(n+1, vector<int>(C+1, 0));
vector<int> x(n, 0);
// 动态规划过程
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= C; j++) {
if (w[i-1] <= j && dp[i-1][j-w[i-1]] + v[i-1] > dp[i-1][j]) {
dp[i][j] = dp[i-1][j-w[i-1]] + v[i-1];
x[i-1] = 1;
}
else {
dp[i][j] = dp[i-1][j];
}
}
}
// 输出结果
cout << "物品选择情况:" << endl;
for (int i = 0; i < n; i++) {
cout << x[i] << " ";
}
cout << endl << "最大总价值为:" << dp[n][C] << endl;
}
int main()
{
// 输入数据
int C, n;
cout << "请输入背包容量C和物品数量n:";
cin >> C >> n;
vector<int> w(n), v(n);
cout << "请输入每个物品的重量和价值:";
for (int i = 0; i < n; i++) {
cin >> w[i] >> v[i];
}
// 调用函数
knapsack01(C, w, v);
return 0;
}
```
上述代码通过二维数组 `dp` 记录了每个子问题的最优解,同时使用一维数组 `x` 记录了选择的物品情况。该算法的时间复杂度为 $O(nC)$,空间复杂度为 $O(nC)$。
2. C++程序实现可以部分装入的背包问题
在部分装入的背包问题中,物品可以被分割为任意大小的部分,因此一个物品可以选择装入一部分,而不必全部装入或全部不装入。这个问题可以通过动态规划求解,具体实现如下:
```cpp
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// 01背包问题的动态规划算法
void knapsack_fraction(int C, vector<int> w, vector<int> v)
{
int n = w.size();
vector<pair<double,int>> vw(n);
for (int i = 0; i < n; ++i) {
vw[i] = make_pair((double)v[i]/w[i], i);
}
sort(vw.rbegin(), vw.rend());
vector<double> x(n, 0);
double value = 0;
for (int i = 0; i < n; ++i) {
if (w[vw[i].second] <= C) {
x[vw[i].second] = 1;
value += v[vw[i].second];
C -= w[vw[i].second];
}
else {
x[vw[i].second] = (double)C/w[vw[i].second];
value += x[vw[i].second] * v[vw[i].second];
C = 0;
break;
}
}
// 输出结果
cout << "物品选择情况:" << endl;
for (int i = 0; i < n; i++) {
cout << x[i] << " ";
}
cout << endl << "最大总价值为:" << value << endl;
}
int main()
{
// 输入数据
int C, n;
cout << "请输入背包容量C和物品数量n:";
cin >> C >> n;
vector<int> w(n), v(n);
cout << "请输入每个物品的重量和价值:";
for (int i = 0; i < n; i++) {
cin >> w[i] >> v[i];
}
// 调用函数
knapsack_fraction(C, w, v);
return 0;
}
```
上述代码中,我们首先计算每个物品的单位价值,然后对物品按照单位价值从大到小排序,依次选择单位价值最大的物品直到背包容量不足为止。如果最后还有剩余的背包容量,则将其全部分配给单位价值最大的物品。这个算法的时间复杂度为 $O(n\log n)$。
总结:部分装入背包问题的算法在一定程度上放宽了背包问题的限制,可以得到更优的结果。但是,由于需要排序,其时间复杂度较高,因此在实际应用中需要根据具体情况选择使用哪种算法。
阅读全文