我遇到如下问题:
您将获得一组$ n $类型的矩形3-D盒子 第i个盒子有高度,宽度,深度和利润。你想创建一个 高度限制H(重量)的盒子堆栈,并最大化的总和 利润,但你只能在另一个盒子的顶部堆叠一个盒子 下盒的2-D底座的尺寸均大或相等 比较高的盒子的二维底座。当然可以 旋转一个框,使任何一侧作为其基础。你也是 允许使用相同类型框的多个实例。
我意识到它是无界背包问题和盒子堆叠问题的组合,只有很小的变化。我尝试使用无界背包算法来解决它,增加了盒子堆叠限制。当我使用递归自上而下方法(代码可用here)时,它可以工作。我想要做的是用memoization实现自上而下的方法,因为我必须返回利润的价值以及挑选的项目。
教授告诉我,我需要使用三维数组来计算问题的结果,所以我尝试实现它(代码可用here)。但是在评论部分提供的帮助下,我意识到我无法在我的机器上运行它。有没有其他方法来存储和检索挑选的物品?
以.data结尾的文件是问题的实例,它们具有以下格式:
num_boxes
max_height(weight)
profit_1
...
profit_num_boxes
width_1
height_1
depth_1
...
width_num_boxes
height_num_boxes
depth_num_boxes
以下是我的代码:
#include <stdio.h>
#include <stdlib.h>
int max_height;
int num_boxes;
int max_dimension;
typedef struct box {
int height, width, depth, profit, rotations;
} Box;
int max(int x, int y) {
return (x > y) ? x : y;
}
Box* readboxes(char* file) {
FILE *in;
int i = 0;
int j = 0;
int k = 0;
int l = 0;
int value;
Box *boxes;
in = fopen(file, "r");
if (in == NULL)
printf("Couldn't open the file\n");
else {
max_dimension = 0;
if ((fscanf(in, "%d", &value)) != EOF) {
num_boxes = value;
i++;
}
boxes = malloc(sizeof(Box) * 2 * num_boxes);
while ((fscanf(in, "%d", &value)) != EOF) {
if (i == 1)
max_height = value;
if (i >= 2 && i < num_boxes + 2) {
boxes[j].profit = value;
j++;
}
if (i >= num_boxes + 2) {
if (k % 3 == 0) {
max_dimension = max(max_dimension, value);
boxes[l].width = value;
}
if (k % 3 == 1) {
max_dimension = max(max_dimension, value);
boxes[l].height = value;
}
if (k % 3 == 2) {
max_dimension = max(max_dimension, value);
boxes[l].depth = value;
}
boxes[l].rotations = 1;
k++;
if (k % 3 == 0)
l++;
}
i++;
}
}
return boxes;
}
void generateRotations(int num_boxes, Box *boxes) {
int index = num_boxes;
for (int i = 0; i < num_boxes; i++) {
boxes[index].height = boxes[i].width;
boxes[index].depth = boxes[i].depth;
boxes[index].width = boxes[i].height;
boxes[index].profit = boxes[i].profit;
boxes[index].rotations = 2;
index++;
}
}
int compare(const void *a, const void * b) {
return ((*(Box *) b).depth * (*(Box *) b).width)
- ((*(Box *) a).depth * (*(Box *) a).width);
}
int*** create3DArray() {
int *** m = malloc((max_height + 1) * sizeof(int**));
for (int i = 0; i < (max_height + 1); i++) {
m[i] = malloc((max_dimension + 1) * sizeof(int *));
for (int j = 0; j < (max_dimension + 1); j++)
m[i][j] = malloc((max_dimension + 1) * sizeof(int));
}
for (int i = 0; i <= max_height; i++)
for (int j = 0; j <= max_dimension; j++)
for (int k = 0; k <= max_dimension; k++)
m[i][j][k] = -1;
return m;
}
void free3DArray(int ***m) {
for (int i = 0; i <= max_height; i++)
for (int j = 0; j <= max_dimension; j++)
free(m[i][j]);
for (int i = 0; i <= max_dimension; i++)
free(m[i]);
free(m);
}
//need help here
int knapsack(int weight, int depth, int width, Box *boxes, int ***m) {
int result_aux;
int weight_aux;
int depth_aux;
int width_aux;
if (m[weight][depth][width] != -1) {
return m[weight][depth][width];
}
else {
m[weight][depth][width] = 0;
for (int i = 0; i < num_boxes; i++) {
weight_aux = weight - boxes[i].height;
depth_aux = boxes[i].depth;
width_aux = boxes[i].width;
if (weight_aux >= 0) {
if (depth_aux <= depth && width_aux <= width) {
result_aux = knapsack(weight_aux, depth_aux, width_aux,
boxes, m) + boxes[i].profit;
if (result_aux > m[weight][depth][width])
m[weight][depth][width] = result_aux;
}
}
}
}
return m[weight][depth][width];
}
int main(int argc, char *argv[]) {
if (argc != 2) {
printf("Arguments: \"in\" ");
} else {
Box *boxes = readboxes(argv[1]);
generateRotations(num_boxes, boxes);
num_boxes = 2 * num_boxes;
qsort(boxes, num_boxes, sizeof(boxes[0]), compare);
int ***m = create3DArray();
printf("Profit: %d\n",
knapsack(max_height, max_dimension, max_dimension, boxes, m));
printf("Number of boxes: %d\n", num_boxes / 2);
printf("Max height: %d\n", max_height);
free(boxes);
free3DArray(m);
}
return 0;
}