Java 带两个结构的背包

Java 带两个结构的背包,java,algorithm,dynamic-programming,knapsack-problem,Java,Algorithm,Dynamic Programming,Knapsack Problem,给定问题: 0/1背包问题,n个物品,每个物品的重量为w_i,值为v_i。找出其重量总和等于重量W的项目的最大总值 但有两种解释: 背包中所有物品的总重量必须精确为W 项目的总数量必须是偶数 我想找到一种兼顾两种解释的算法。我已经发现如何在同一时间关注其中一个问题 这是我的实施方案,它关注于构造1(精确重量W): 公共类背包重量{ 公共静态void main(字符串[]args){ int[]w=newint[]{4,1,5,8,3,9,2};//权重 int[]v=新的int[]{2,12,8

给定问题:

0/1背包问题,n个物品,每个物品的重量为w_i,值为v_i。找出其重量总和等于重量W的项目的最大总值

但有两种解释:

  • 背包中所有物品的总重量必须精确为W
  • 项目的总数量必须是偶数
  • 我想找到一种兼顾两种解释的算法。我已经发现如何在同一时间关注其中一个问题

    这是我的实施方案,它关注于构造1(精确重量W):

    公共类背包重量{
    公共静态void main(字符串[]args){
    int[]w=newint[]{4,1,5,8,3,9,2};//权重
    int[]v=新的int[]{2,12,8,9,3,4,3};//值
    int n=w长度;
    int W=10;//W(最大重量)
    int[][]DP=新int[n+1][W+1];
    对于(int i=1;i=0){
    DP[i][j]=数学最大值(DP[i-1][j],DP[i-1][j-w[i-1]]+v[i-1]);
    }否则{
    DP[i][j]=-Integer.MAX_值;
    }
    }
    }
    System.out.println(“结果:+DP[n][W]);
    }
    }
    结果:22
    
    以下是我的实现,其中考虑了constrait 2(项目数量为偶数):

    公共类背包金额{
    公共静态void main(字符串[]args){
    int[]权重=新的int[]{4,1,5,8,3,9,2};//权重
    int[]values=新的int[]{2,12,8,9,3,4,3};//值
    int n=权重。长度;
    int W=10;
    int[]DP_奇数=新int[n+1][W+1];
    int[]DP_偶数=新int[n+1][W+1];
    对于(int i=0;i=0){
    如果(DP_奇[i-1][j-权重[i-1]]>=0){
    DP_偶[i][j]=数学最大值(DP_偶[i-1][j],DP_奇[i-1][j-权重[i-1]+值[i-1]);
    }
    如果(DP_偶数[i-1][j-权重[i-1]]>=0){
    DP_奇[i][j]=数学最大值(DP_奇[i-1][j],DP_偶[i-1][j-权重[i-1]+值[i-1]);
    }
    }
    如果(i>0){
    DP_奇[i][j]=Math.max(DP_奇[i][j],DP_奇[i-1][j]);
    DP_偶[i][j]=Math.max(DP_偶[i][j],DP_偶[i-1][j]);
    }
    }
    }
    System.out.println(“结果:+DP_偶数[n][W]);
    }
    }
    结果:21
    
    其思想是:我使用两个DP表(DP_偶数和DP_奇数),并为DP_奇数中包含奇数项的背包和DP_偶数中包含偶数项的背包保存最佳解决方案

    现在我的问题是如何实现这两种结构协同工作。有办法解决这个问题吗


    (如果我的问题中有什么不清楚的地方,请提问!)

    不确定这是否是解决此问题的最佳方法,但我在这里所做的是首先减少问题以适应约束条件。首先找到重量等于背包重量的物品的可能偶数,然后找到价值最高的组合

    import java.util.Scanner;
    import static java.lang.Math.pow;
    
    public class subSet{
    
    void subset(int num,int n, int x[])
    {
        int i;
        for(i=1;i<=n;i++)
            x[i]=0;
        for(i=n;num!=0;i--)
        {
            x[i]=num%2;
            num=num/2;
        }
    }
    public static void main(String[] args) {
        int n,d,sum,present=0;
        int j;
        System.out.println("enter the number of items");
        Scanner sc=new Scanner(System.in);
        n=sc.nextInt();
        int a[]=new int[n+1];
        int x[]=new int[n+1];
        System.out.println("enter the weights of items");
        for(int i=1;i<=n;i++)
            a[i]=sc.nextInt();
        System.out.println("enter the values of items");
        int v[]=new int[n+1];
        for(int i=1;i<=n;i++)
            v[i]=sc.nextInt();
        System.out.println("enter the max weight");
        d=sc.nextInt();
    
        int sol=0;int max=0;
        if(d>0)
        {
            for(int i=1;i<=Math.pow(2,n)-1;i++)
            {
                subSet s=new subSet();
                s.subset(i,n,x);
                sum=0;int count=0;
                for(j=1;j<=n;j++)
                    if(x[j]==1)
                    {
                        sum=sum+a[j];
                        count++;
                    }
                sol=0;
                if(d==sum && count%2==0)
                {
                    present=1;
                    for(j=1;j<=n;j++)
                    {
                        if(x[j]==1)
                            sol=v[j]+sol;
                        if(sol>max)
                            max=sol;
                    }
                }
    
            }
    
        }
        if(present==0)
            System.out.println("Solution does not exists");
        else
            System.out.print("solution = "+max);
    
    }
    }
    
    import java.util.Scanner;
    导入静态java.lang.Math.pow;
    公共类子集{
    无效子集(int num、int n、int x[])
    {
    int i;
    
    对于(i=1;i我认为问题可能在于这一行:

    DP_odd[i][j] = -1;
    
    如果使用了奇数次,您只会受到1的处罚


    如果你只是简单地将它增加到一个更大的负数(例如整数的最大负值),我认为你当前的算法应该可以工作。

    第二个算法有什么问题?你能举个例子说明它没有给出正确的答案吗?对我来说,它似乎已经包含了这两个约束条件?现在它使用w[1](=1)和w[3](=8),所以第一个构造不是真的,因为1+8=9!=10。如果同时考虑两个构造(w[0],w[1],w[4]和w[6],它们的重量为10,值为20),结果应该是20。很好,但正如你已经说过的,它没有那么有效。但无论如何,谢谢!
    import java.util.Scanner;
    import static java.lang.Math.pow;
    
    public class subSet{
    
    void subset(int num,int n, int x[])
    {
        int i;
        for(i=1;i<=n;i++)
            x[i]=0;
        for(i=n;num!=0;i--)
        {
            x[i]=num%2;
            num=num/2;
        }
    }
    public static void main(String[] args) {
        int n,d,sum,present=0;
        int j;
        System.out.println("enter the number of items");
        Scanner sc=new Scanner(System.in);
        n=sc.nextInt();
        int a[]=new int[n+1];
        int x[]=new int[n+1];
        System.out.println("enter the weights of items");
        for(int i=1;i<=n;i++)
            a[i]=sc.nextInt();
        System.out.println("enter the values of items");
        int v[]=new int[n+1];
        for(int i=1;i<=n;i++)
            v[i]=sc.nextInt();
        System.out.println("enter the max weight");
        d=sc.nextInt();
    
        int sol=0;int max=0;
        if(d>0)
        {
            for(int i=1;i<=Math.pow(2,n)-1;i++)
            {
                subSet s=new subSet();
                s.subset(i,n,x);
                sum=0;int count=0;
                for(j=1;j<=n;j++)
                    if(x[j]==1)
                    {
                        sum=sum+a[j];
                        count++;
                    }
                sol=0;
                if(d==sum && count%2==0)
                {
                    present=1;
                    for(j=1;j<=n;j++)
                    {
                        if(x[j]==1)
                            sol=v[j]+sol;
                        if(sol>max)
                            max=sol;
                    }
                }
    
            }
    
        }
        if(present==0)
            System.out.println("Solution does not exists");
        else
            System.out.print("solution = "+max);
    
    }
    }
    
    DP_odd[i][j] = -1;