public double knapsack(double[] pp,double[] ww,double cc){ //初始化 c=cc; n=pp.length-1; cw=0; cp=0; bestp=0; x=new int[n+1]; bestx=new int[n+1]; //q为单位重量价值数组 q=new Element[n+1]; for(int i=0;i<=n;i++){ q[i]=new Element(i,pp[i]/ww[i]); } //将个物品依单位重量价值从大到小排列 java.util.Arrays.sort(q); //MergeSort.mergeSort(q); p=new double[n+1]; w=new double[n+1]; for(int i=1;i<=n;i++){ p[i]=pp[q[i].id]; w[i]=ww[q[i].id]; } backtrack(1); return bestp; } public void backtrack(int i){ if(i>n){//到达叶子节点 bestp=cp; for(int j=1;j<=n;j++){//保存最优值对应的包的编号 bestx[j]=x[j]; } return; } if(cw+w[i]<=c){//左子树 x[i]=1; cw+=w[i]; cp+=p[i]; backtrack(i+1); cw-=w[i];//恢复现场 cp-=p[i]; } if(bound(i+1)>bestp){ x[i]=0; backtrack(i+1); } } public double bound(int i){//上界函数 double cleft=c-cw; double bound=cp; while(i<=n&&w[i]<=cleft){ cleft-=w[i]; bound+=p[i]; i++; } if(i<=n){ bound+=p[i]*cleft/w[i]; } return bound; } public static void main(String[] args) { double[] weight= {3,5,7,8,9}; double[] price= {4,6,7,9,10}; double cc=100; knapsack1 k=new knapsack1(); double best=k.knapsack(price,weight,cc); System.out.println("最优值:"+best); System.out.println("选中的物品编号分别是:"); for(int i=1;i<k.bestx.length;i++){ if(k.bestx[i]==1){ System.out.print(k.q[i].id+" ");这段代码每行啥意思
时间: 2024-01-22 16:04:23 浏览: 68
这段代码实现了一个 0/1 背包问题的解法。其中,`knapsack` 方法接收三个参数:`pp` 表示每个物品的价值,`ww` 表示每个物品的重量,`cc` 表示背包的容量。在方法内部,首先将物品按照单位重量价值从大到小排序,然后通过回溯算法求出最优解。具体来说,回溯算法通过递归遍历决策树来找到最优解,其中的 `backtrack` 方法表示回溯的过程,`bound` 方法表示求解上界的函数。最后,打印出选中的物品编号以及最优值。
相关问题
public double knapsack(double[] pp,double[] ww,double cc){ //初始化 c=cc; n=pp.length-1; cw=0; cp=0; bestp=0; x=new int[n+1]; bestx=new int[n+1]; //q为单位重量价值数组 q=new Element[n+1]; for(int i=0;i<=n;i++){ q[i]=new Element(i,pp[i]/ww[i]); } //将个物品依单位重量价值从大到小排列 java.util.Arrays.sort(q); //MergeSort.mergeSort(q); p=new double[n+1]; w=new double[n+1]; for(int i=1;i<=n;i++){ p[i]=pp[q[i].id]; w[i]=ww[q[i].id]; } backtrack(1); return bestp; } public void backtrack(int i){ if(i>n){//到达叶子节点 bestp=cp; for(int j=1;j<=n;j++){//保存最优值对应的包的编号 bestx[j]=x[j]; } return; } if(cw+w[i]<=c){//左子树 x[i]=1; cw+=w[i]; cp+=p[i]; backtrack(i+1); cw-=w[i];//恢复现场 cp-=p[i]; } if(bound(i+1)>bestp){ x[i]=0; backtrack(i+1); } } public double bound(int i){//上界函数 double cleft=c-cw;
你的代码是用来解决背包问题的,其中的 bound 函数是用来计算当前节点的上界值。它首先将剩余容量 cleft 初始化为背包剩余容量,然后计算从当前节点到叶子节点所能够获得的最大价值 bound,其中,价值包括已经放进去的物品价值和剩下的物品按单位重量价值排名后取前缀所能够获得的价值。这个函数的返回值就是上界值 bound。
运用贪心算法,每次挑选目前单价最高且重量未超过背包剩余容量的物品。补全以下代码#include <iostream.h> #include <stdio.h> typedef struct { char name[16]; // 名称 double p; // 价值 double w; // 重量 double r; // 单价 }good; int main() { int n, i, j, k; good *G, temp; double C; // 存储当前背包容量 double value; // 背包当前所装物品总价 freopen("Knapsack.in", "r", stdin); freopen("Knapsack.out", "w", stdout); cin>>n; cin>>C; G = new good[n]; for(i=0; i<n; i++) { cin>>G[i].name; cin>>G[i].p; cin>>G[i].w; G[i].r=G[i].p/G[i].w; } //************************************************ //================================================= cout<<"Total price: "<<((int)(100*value+0.5))*0.01<<endl; return 0; }
补全的代码如下:
```c++
#include <iostream>
#include <stdio.h>
#include <algorithm>
using namespace std;
typedef struct {
char name[16]; // 名称
double p; // 价值
double w; // 重量
double r; // 单价
} good;
// 比较函数,用于排序
bool cmp(good a, good b) {
return a.r > b.r;
}
int main() {
int n, i, j, k;
good *G, temp;
double C; // 存储当前背包容量
double value = 0; // 背包当前所装物品总价
freopen("Knapsack.in", "r", stdin);
freopen("Knapsack.out", "w", stdout);
cin >> n;
cin >> C;
G = new good[n];
for(i = 0; i < n; i++) {
cin >> G[i].name;
cin >> G[i].p;
cin >> G[i].w;
G[i].r = G[i].p / G[i].w;
}
// 按照单价从高到低排序
sort(G, G + n, cmp);
// 按照贪心算法选择物品
for(i = 0; i < n; i++) {
if(G[i].w <= C) { // 若当前物品可以放入背包
C -= G[i].w; // 更新背包容量
value += G[i].p; // 更新背包所装物品总价
} else { // 若当前物品无法放入背包
value += G[i].r * C; // 将背包剩余容量全部用于装当前物品
break;
}
}
// 输出结果
cout << "Total price: " << ((int)(100 * value + 0.5)) * 0.01 << endl;
return 0;
}
```
代码中使用了 `sort` 函数进行排序,需要添加头文件 `algorithm`。在选择物品时,如果当前物品无法放入背包,则将背包剩余容量全部用于装当前物品,这是贪心算法的核心思想之一。最后输出结果时,使用了四舍五入的方法,即将数值乘以 100 后加上 0.5,再取整数部分,最后除以 100。
阅读全文