0/1背包问题 回溯

0/1背包问题

描述:

0/1背包问题。给定一载重量为W的背包及n个重量为wi、价值为vi的物体,1≤i≤n,要求而且重量和恰好为W具有最大的价值。

输入格式:

第一行输入背包载重量W及背包个数n,再依次输入n行,每行为背包重量wi和价值vi。

输出格式:

第一行输出装入背包内的物体编号(末尾有空格),若没有任何物品能装入,输出: No,第二行输出背包内的物体总价值。

输入样例:

5 10
2 6
2 3
6 5
5 4
4 6

输出样例

1 2 5
15

输入样例:

2 10
11 2
13 100

输出样例

No
0

import java.io.*;
@SuppressWarnings("all")
public class backtracking_0_1_backpack {//0-1背包问题回溯 剪枝

    static int max;
    private static int bound(int i,int n,int []v) {//计算剩余价值 i - n-1 的价值(找出剩余价值)
        int sum = 0;
        while (i < n){
            sum += v[i++];
        }
        return sum;
    }
    //i 表示当前位置下标,n表示背包个数,W表示背包容量,cw表示当前重量,cv表示当前价值,v表示每个背包价值,record记录暂时最优路径,path表示最终最优路径
    private static void dfs(int i,int n,int W,int cw,int cv,int []w,int []v,int []record,int []path) {
        if(i == n) {//i == n,表示遍历到了叶节点  开始回溯
            max = cv;
            for(int j = 0;j < n;j++) {
                path[j] = record[j];
            }
            return;
        }

        if(cw + w[i] <= W) {//当前重量 + 下一个要装入的 物品重量 小于背包容量(就是下一个物品可以装入的情况下)  ==相当于加枝==
            record[i] = 1;
            dfs(i + 1,n,W,cw + w[i],cv + v[i],w,v,record,path);
        }

        if(cv + bound(i +1,n,v) > max) {//当不算当前价值,背包现有价值 + 剩余价值 > 当前找到最大价值,说明可能还有最优解,继续深层遍历 小于的话直接剪枝 ==相当于剪枝==
            record[i] = 0;
            dfs(i+1,n,W,cw,cv,w,v,record,path);
        }
    }

    public static void main(String args[]) throws IOException{//0-1背包问题回溯 剪枝
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        String []s = reader.readLine().split(" ");
        int n = Integer.parseInt(s[0]);//物品个数
        int W = Integer.parseInt(s[1]);//背包容量
        int []w = new int[n];
        int []v = new int[n];
        int []record = new int[n];//临时记录那个物品被装入
        int []path = new int[n];//记录那个物品被装入
        for(int i = 0;i < n;i++) {
            s = reader.readLine().split(" ");
            w[i] = Integer.parseInt(s[0]);
            v[i] = Integer.parseInt(s[1]);
        }
        max = -1;
        dfs(0,n,W,0,0,w,v,record,path);
        for(int i = 0;i < n;i++) {
            if(path[i] == 1) {
                System.out.print(i + 1 + " ");
            }
        }
        if(max == 0) {//那个物品都装不下的时候
            System.out.print("No");
        }
        System.out.print("\n" +max);
    }
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值