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