11.0-1背包问题

1.问题解析:

有 n 件物品和一个承受重量为 C 的背包。第 i 件物品的重量是 w[i],价值是 v[i]。求解将哪些物品装入背包可使这些物品的重量总和不超过背包承受重量j,且价值总和最大。

其中x=(X1,X2,...Xn)为最优解,其中Xn为0或1.要求满足sum(Xi*w[i])<=C,sum(Xi*v[i])最大

 

2.最优子结构(其中j=1,2,3,4,5...C)

   .1若w[i]>j,则x=(X1,X2,...Xn-1)为w=(w[1],w[2],w[3]...w[n-1]),v=(v[1],v[2],v[3]...v[n-1])的最优解

   .2若w[i]<=j,则情况一:如果Xn=0,则x=(X1,X2,...Xn-1)为w=(w[1],w[2],w[3]...w[n-1]),v=(v[1],v[2],v[3]...v[n-1])的最优解;

                        情况二:如果Xn=1,则x=(X1,X2,...Xn-1)为w=(w[1],w[2],w[3]...w[n-1]),v=(v[1],v[2],v[3]...v[n-1])的最优解;

   表示如图:

算法伪代码:

KNAPSACK(v,w,C)

1.    n<-length[v]

2.    for j<-0 to C

3.      do m[0,j]<-0

4.    for i<-1 to n

5.      do m[i,0]<-0

6.        for j<-1 to C

7.          do m[i,j]<-m[i-1,j] //无论是否wi与j的关系如何,肯定是满足此式子的,但如果存在 wi <=j,可以考虑下如果原来条件下加上最后一个的价值,并且还要满足其质量j-wi

8.            if wi <=j

9.            then if vi+m[i-1,j-wi]>m[i-1,j]

10.              then m[i,j]<-vi+m[i-1,j-wi]

11.    return m

 

3.构造最优解

BUILD-SOLUTION(m,w,C)

1.    n<-length(w)

2.    j<-C

3.    for i<-n to 1

4.      do if m[i,j]=m[i-1,j]  //如果两者相等,就说明最后一个没用到,所以x[i]=0

5.          then x[i]=0

6.          else x[i]=1

7.                  j<-j-w[i]

8.    return x

 

C:

knapsack.h

#define _knapsack_h
#include<malloc.h>
int *knapsack(int *w,int *v,int n,int c){
int *m=(int*)malloc((n+1)*(c+1)*sizeof(int)),i,j;//建立一个表格来存放价值
for(i=1;i<n+1;i++)
    m[i*(c+1)]=0;
for(j=0;j<c+1;j++)
    m[j]=0;
for(i=1;i<=n;i++)
    for(j=1;j<=c;j++){
       m[i*(c+1)+j]=m[(i-1)*(c+1)+j];
if(w[i-1]<=j)
    if(v[i-1]+m[(i-1)*(c+1)+j-w[i-1]]>m[(i-1)*(c+1)+j])
        m[i*(c+1)+j]=v[i-1]+m[(i-1)*(c+1)+j-w[i-1]];
}
    return m;
}
int *buildsolution(int *m,int n,int *w,int c ){
int i,j=c;
int *x=(int*)malloc(n*sizeof(int));
for(i=n;i>=1;i--)
    if(m[i*(c+1)+j]==m[(i-1)*(c+1)+j])
        x[i-1]=0;
    else{
        x[i-1]=1;
        j-=w[i-1];
    }
    return x;
}

 

main.cpp

#include"knapsack.h"
#include<stdlib.h>
#include<stdio.h>
int main(){
    int w[]={2,3,4,5},v[]={3,4,5,7};
    int *m,*x,i;
    m=knapsack(w,v,4,9);
    x=buildsolution(m,4,w,9);
    for(i=0;i<4;i++)
        printf("%d",x[i]);
    printf("\n");
    free(m);
}

输出结果:

JAVA:

Knapsack.java

package Jamin;

public class Knapsack {
public static int[][] knapsack(int[] w,int[] v,int c){
    int i,j,n=w.length;
    int[][] m=new int [n+1][c+1];
    for(i=1;i<n+1;i++)
        m[i][0]=0;
    for(j=1;j<c+1;j++)
        m[0][j]=0;
    for(i=1;i<=n;i++)
        for(j=1;j<=c;j++) {
            m[i][j]=m[i-1][j];
    if(w[i-1]<=j)
        if(v[i-1]+m[i-1][j-w[i-1]]>m[i-1][j])
            m[i][j]=v[i-1]+m[i-1][j-w[i-1]];
}
    return m;
}
public static int[] buildsolution(int[][] m,int[] w,int c) {
    int i,j=c,n=w.length;
    int[] x=new int[n];
    for(i=n;i>=1;i--)
        if(m[i][j]==m[i-1][j])
            x[i-1]=0;
        else {
            x[i-1]=1;
            j-=w[i-1];
        }
    return x;
}
}
 

Test.java

package Jamin;

public class Test {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
int w[]= {2,3,4,5},v[]= {3,4,5,7};
int[][] m;
int[] x;
m=Knapsack.knapsack(w, v, 9);
x=Knapsack.buildsolution(m, w, 9);
for(int i=0;i<4;i++)
    System.out.print(x[i]+" ");
System.out.println();
    }

}
 

输出结果:

1 1 1 0 
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值