编辑代码

#include<stdio.h>
#define M 14//表示二维数组中给的体积容量最多是13,即二维数组a的列
#define N 6//这个表示二维数组a的行数,即待选商品
typedef struct	Goods {//对于结构体,如果要改结构体名字,注意要加typedef这个关键字
	char* name;
	int price;//表示商品的价格
	int volume;//表示商品的体积
}Goods;
void Printf(int a[][M]) {
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < M; j++) {
			printf("%3d", a[i][j]);
		}
		printf("\n");
	}
	return;
}
//涉及重点知识:二维数组的传参
 
void PackGoods(Goods goods[], int a[][14]) {
	int MaxPrice , j;
	//先将a数组中当第一阶段 要挑选商品为0时候,即a[0][] 初始化为0
	//为什么要初始化0呢?以为当待选商品为0时候,都没有可以选的,何来价格之说
	for (int i = 0; i < M; i++) {
		a[0][i] = 0;
	}
	//初始化a数组中当背包容量为0时
	for (int i = 0, j = 0; i < N; i++) {
		a[i][j] = 0;
	}
	//
	for (int i = 1; i < N; i++) {
		//先初始化第i行,即第i阶段的最优子结构的解
		for (int j = 1; j < M; j++) {
			a[i][j] = a[i - 1][j];
		}
		//注意j >= goods[i].volume这个判断条件,不可以写到for循环判断语句中
		for (int j = 1; j < M; j++) {
			//状态转移方程
			if (goods[i].price + a[i - 1][j - goods[i].volume] > a[i - 1][j] && j >= goods[i].volume) {
				a[i][j] = goods[i].price + a[i - 1][j - goods[i].volume];
			}
			if (j == 13) {
				break;
			}
		}
	}
	//最高价格为MaxPrice
	MaxPrice = a[N - 1][M - 1];
	printf("最大的价格为:%d\n", MaxPrice);
	//打印出购买的物件
	j = M - 1;
	for (int i = N - 1; i >= 1; i--) {
		if (a[i][j] != a[i - 1][j]) {//表示购买了这阶段的主体商品
			printf("买了%s,价格为%d\n", goods[i].name, goods[i].price);
			j = j - goods[i].volume;//这一句必须写在if里边,在外边会产生越界,但是编译器查不出来
		}
		//j = j - goods[i].volume; printf("%d\n", j);
		//上面的写法时错的,必须要写在if里边
	}
	return;
}
 
void main() {
	//为了配合a数组的商品序号,让其一致,我们将下标控制到由1开始
	Goods goods[6] = { {0}, {"啤酒",24,10},{"汽水",2,3},{"饼干",9,4},{"面包",10,5},{"牛奶",9,4 } };
	//1. 数组a,用于存储每个阶段最优子结构的解
	//2. 其中一维中1~5表示商品
	//3. 其中二维中0~13表示给该阶段所给的体积
	int a[6][14];
	PackGoods(goods, a);
	Printf(a);
	return;
}