背包问题

1.01背包,每种类型只能取一次

法1,二维Dp:

public int Pack01(int[] w,int[] v,int n,int sum) {
        int[][] dp=new int[n+1][sum+1];//dp[i][j]前i件物品,总重量不超过j的最大价值
        for(int i=1;i<=n;i++) {
            for(int j=sum;j>0;j--) {//这里一定是从大到小
                if(w[i-1]<=j) dp[i][j] = Math.max(dp[i-1][j], dp[i-1][j-w[i-1]]+v[i-1]);
                else dp[i][j] = dp[i-1][j];
            }
        }
        return dp[n][sum];
    }

法2,一维Dp

public int Pack01(int[] w,int[] v,int n,int sum) {
        int[] dp=new int[sum+1];//dp[i]总重量不超过i的最大价值
        for(int i=1;i<=n;i++) {
            for(int j=sum;j>=w[i-1];j--) {
                if(dp[j-w[i-1]]+v[i-1]>dp[j]) dp[j]=dp[j-w[i-1]]+v[i-1];
            }
        }
        return dp[sum];
    }

法三,搜索

public void Pack01(int curi,int curw,int curv,int[] w,int[] v) {
        if(curi>N-1) {
            if(curv>best) {
                best=curv;
            }
            return;
        }
        if(curw+w[curi]<=Sum) {
            Pack01(curi+1,curw+w[curi],curv+v[curi],w,v);
        }
        Pack01(curi+1,curw,curv,w,v);
}

2.完全背包,每种物品可以无限用

public int PackComplete(int[] w,int[] v,int n,int sum) {
        int[] dp=new int[sum+1];//dp[i]总重量不超过i的最大价值
        for(int i=1;i<=n;i++) {
            for(int j=w[i-1];j<=sum;j++) {//这里就需要从前往后了,因为每个物品都可以重复使用,前面用了,后面继续用
                if(dp[j-w[i-1]]+v[i-1]>dp[j]) dp[j]=dp[j-w[i-1]]+v[i-1];
            }
        }
        return dp[sum];
    }

3.多重背包,可以把它当做01背包来理解(依旧从后往前)

public int PackMultiple(int[] w,int[] v,int[] m,int n,int sum) {
        int[] dp=new int[sum+1];//dp[i]总重量不超过i的最大价值
        for(int i=1;i<=n;i++) {
            for(int j=sum;j>=0;j--) {
                for(int k=0;k<=m[i-1];k++) {
                    if(j-k*w[i-1]<0) break;
                    dp[j]=Math.max(dp[j], dp[j-k*w[i-1]]+k*v[i-1]);
                }        
            }
        }
        return dp[sum];
    }

 

posted @ 2019-07-25 15:20  LeeJuly  阅读(144)  评论(0)    收藏  举报