【回溯法】01背包问题——求最大价值路径
题目描述
给定n种物品,背包的容量是c,物品i的重量是wi,其价值为vi。应如何选择装入背包的物品(不是问最大的总价值是多少),使得装入背包中物品的总价值最大?
示例
输入描述:
个数n 容量c
重量1,重量2,......
价值1,价值2,......
输出:
总价值
对应的物品编号
输入:
4
8
2 3 4 5
3 4 5 6
输出:
10
2 4
思路
回溯法,dfs遍历各种可能,记录当前价值curValue和当前最大价值bestValue。
当dfs访问超过物品编号范围时,比较curValue和bestValue的值,更新最大价值和最大价值对应的物品列表。
当dfs访问在正常的物品编号范围时,分为
1、加入当前物品(需要判断加入后会不会大于背包容量)
2、不加入当前物品
代码
public class backpack01 {
static int n;
static int c;
static int []w;
static int []v;
static int []visited;
static int []best;
static int bestValue = 0, curValue = 0, curWeight = 0;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
c = sc.nextInt();
w = new int[n+1];
v = new int[n+1];
visited = new int[n+1];
best = new int[n+1];
for(int i = 1;i <= n;++i){
w[i] = sc.nextInt();
}
for(int i = 1;i <= n;++i){
v[i] = sc.nextInt();
}
for(int i = 0;i <= n;++i){
visited[i] = 0;
best[i] = 0;
}
dfs(1);
System.out.println("最大值:" + bestValue);
System.out.println("最优解: ");
for (int i=0;i<=n;++i){
if (best[i] != 0) {
System.out.print(i + " ");
}
}
}
static void dfs(int d) {
if (d > n) {
if (curValue > bestValue) {
bestValue = curValue;
for (int i = 0; i <= n; ++i) {
best[i] = visited[i];
}
}
}
else {
visited[d] = 0;
dfs(d+1);
visited[d] = 1;
if(curWeight + w[d] <= c){
curWeight += w[d];
curValue += v[d];
dfs(d+1);
curWeight -= w[d];
curValue -= v[d];
}
}
}
}