如何使用自上而下的方法检索无界背包的拾取物品

时间:2018-04-28 21:33:05

标签: c dynamic-programming

我遇到如下问题:

  

您将获得一组$ 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;
}

0 个答案:

没有答案