C语言写法
C语言自定义函数声明:
-
先在全局声明:
-
把自定义函数写在main函数(入口函数)前面:
int Sort(int A[], int low,int high){
return 0;
}
int QuickSort(int A[],int low,int high){
return 0;
}
//. 主函数入口 (写在自定义函数后面)
int main(){
QuickSort(A, low, high); //. 调用
Sort(A, low, high);
}
C语言二维数组的定义:
例如:
# include<stdio.h>
int Knapsack01(int V[], int W[],int c, int len); //.自定义函数声明
int main(){
int V[]= {10,3,4,5,4}; //. 物品所占背包容积
int W[] = {24,2,9,10,9}; //. 物品的价值
int len = sizeof(V)/sizeof(V[0]); //.一共有几个物品
// printf("%d\n",len);
Knapsack01(V,W,13,len); //. 背包的总容积设为13
}
int Knapsack01(int V[], int W[],int c, int len){
int p[len][c]; //.定义备忘录数组
int rec[len][c]; //.定义追踪数组
for(int i=0; i<=c; i++) //.填表,其中第一行和第一列全为0,即 V(i,0)=V(0,j)=0;
p[0][i] = 0; //.将每一列的第一个初始化为0(也就是第0行)
for(int i=0; i<len+1; i++)
p[i][0] = 0; //.将每一行的第一个初始化为0(也就是第0列)
for(int i=1; i<=len; i++){
printf("V[%d] = %d\n",i-1,V[i-1]); //. w与v都是从0开始存的,所以开始i=1时对应0的位置
for(int j=1; j<=c; j++){
if(V[i-1]<=j && p[i-1][j-V[i-1]]+W[i-1]>p[i-1][j]){
p[i][j] = p[i-1][j-V[i-1]]+W[i-1];
rec[i][j] = 1;
}//.if
else{
p[i][j] = p[i-1][j];
rec[i][j] = 0;
printf("p[%d][%d] = %d.. ",i-1,j,p[i-1][j]);
}//.else
printf("p[%d][%d] = %d,",i,j,p[i][j]);
}//.for
printf("\n");
}//.for
}
感觉自己写的逻辑上没有问题。。。。但是结果就是有些地方不对
按理说p[5][13]应该是28(最右下角):
窒息了。。。。我再肝!肯定是哪里出了问题
Python做法
1、分析题目
设 f(k ,v)为第 k 件物品,v 为背包剩余容量。那么,这件物品在此刻有两种可能,①.背包装不下。②.背包能装下。其中②又有两种可能,a. 能装下但不装。b.装。
由此可以得出状态转移方程:
观察得出每个f(k ,v)与上一次选或不选有关,所以推出备忘录数组(演算的最右下角应该也是8):
代码如下:
def ZeroOneBag(n, v, b):
memo = [[0 for i in range(v+1)] for i in range(n+1)]
MaxCost = 0
for i in range(1,n+1): ## 注意:i 代表备忘录数组中的行号,j 代表列号
for j in range(1,v+1):
if(j < b[i-1][0]):
memo[i][j] = memo[i-1][j]
else:
memo[i][j] = max(memo[i-1][j], memo[i-1][j-b[i-1][0]]+b[i-1][1])
MaxCost = max(memo[i][j], MaxCost)
return MaxCost
n, v = map(int,input().split())
b = []
for i in range(n):
a = list(map(int,input().split()))
b.append(a)
ZeroOneBag(n, v, b)
值得注意的是,代码中的备忘录数组和演算的不同,我没有在代码中做{ f(k ,v),当vk>v时,f(k ,v)= 0 }的判断。
所以,代码得出的备忘录数组为:
但是,问题不大,编译通过:
代码还是有点繁琐,备忘录数组可以改进,改进思想为:不需要二维数组,而是一个一维数组,长度为背包容量的大小,每个数值代表该容量所能装下物品的最大值。
def ZeroOneBag(N, V, v, w):
memo = [0 for i in range(V+1)] ## 备忘录数组
for i in range(N):
for j in range(V,v[i]-1,-1): ## 从最大容量开始向前循环到当前物品需要的最小容量(比v[i]小的容量再循环下去也没有意义)
memo[j] = max(memo[j], memo[j-v[i]]+w[i]) ## 更新备忘录数组中当前容量的最大价值
print(memo[-1])
N, V = map(int,input().split())
v, w = [], [] ## v为容量数组,w为价值数组
for i in range(N):
a, b = map(int, input().split())
v.append(a); w.append(b)
ZeroOneBag(N, V, v, w)