我正在尝试在C语言的Packing Blocks into a Fixed Rectangle
部分复制this算法,并且我已经对此做了一个question,该问题的解决方案是正确的,但是没有。 t解决了整体问题。我发现了导致“错误”的特定输入,并表明了这一点,我在代码中静态设置了这些值,以使其易于测试。
#include <stdio.h>
#include <stdlib.h>
#define COUNT 10
typedef struct Block
{
struct Node* fit;
int width;
int height;
int x;
int y;
int id;
} Block;
typedef struct Node
{
struct Node* parent;
struct Node* down;
struct Node* right;
int used;
int width;
int height;
int x;
int y;
} Node;
Node *findNode(Node *root, int w, int h);
Node *splitNode(Node **node, int w, int h);
void print2D(Node *root, int space);
int MAX(int a, int b);
int MIN(int a, int b);
int main()
{
Node *root;
Block **blocks;
int boardWidth, boardHeight, totalBlocks;
int i, j;
boardWidth = 500;
boardHeight = 500;
root = malloc(sizeof(Node));
root->x = 0;
root->y = 0;
root->width = boardWidth;
root->height = boardHeight;
root->down = NULL;
root->right = NULL;
root->used = 0;
totalBlocks = 8;
blocks = malloc(totalBlocks * sizeof(Block));
blocks[0] = malloc(sizeof(Block));
blocks[0]->width = 50;
blocks[0]->height = 50;
blocks[0]->id = 0;
blocks[1] = malloc(sizeof(Block));
blocks[1]->width = 50;
blocks[1]->height = 50;
blocks[1]->id = 1;
blocks[2] = malloc(sizeof(Block));
blocks[2]->width = 102;
blocks[2]->height = 20;
blocks[2]->id = 2;
blocks[3] = malloc(sizeof(Block));
blocks[3]->width = 102;
blocks[3]->height = 20;
blocks[3]->id = 3;
blocks[4] = malloc(sizeof(Block));
blocks[4]->width = 102;
blocks[4]->height = 20;
blocks[4]->id = 4;
blocks[5] = malloc(sizeof(Block));
blocks[5]->width = 102;
blocks[5]->height = 20;
blocks[5]->id = 5;
blocks[6] = malloc(sizeof(Block));
blocks[6]->width = 102;
blocks[6]->height = 20;
blocks[6]->id = 6;
blocks[7] = malloc(sizeof(Block));
blocks[7]->width = 500;
blocks[7]->height = 350;
blocks[7]->id = 7;
// Bubble Sort
for (i = 0; i < totalBlocks; i++) {
for (j = 0; j < totalBlocks - i - 1; j++) {
int maxJ = MAX(blocks[j]->height, blocks[j]->width);
int minJ = MIN(blocks[j]->height, blocks[j]->width);
int maxJ1 = MAX(blocks[j + 1]->height, blocks[j + 1]->width);
int minJ1 = MIN(blocks[j + 1]->height, blocks[j + 1]->width);
if (maxJ < maxJ1) {
Block *b = blocks[j];
blocks[j] = blocks[j + 1];
blocks[j + 1] = b;
}
else if (maxJ == maxJ1 && minJ < minJ1) {
Block *b = blocks[j];
blocks[j] = blocks[j + 1];
blocks[j + 1] = b;
}
}
}
// FIT
for (i = 0; i < totalBlocks; i++) {
Block *block = blocks[i];
Node *node;
Node * auxNode = root;
printf("=======================================================");
print2D(auxNode, 0);
if (node = findNode(root, block->width, block->height)) {
block->fit = splitNode(&node, block->width, block->height);
}
}
for (i = 0; i < totalBlocks; i++) {
Block *block = blocks[i];
if (block->fit != NULL) {
printf("x %d y %d\n", block->fit->x, block->fit->y);
printf("w %d h %d\n", block->width, block->height);
printf("\n");
}
}
return 0;
}
Node *findNode(Node *root, int w, int h) {
if (root->used == 1) {
Node * rightNode = findNode(root->right, w, h);
if (rightNode != NULL)
return rightNode;
Node * downNode = findNode(root->down, w, h);
return downNode;
}
else if ((w <= root->width) && (h <= root->height)) {
return root;
}
else {
return NULL;
}
}
Node *splitNode(Node **node, int w, int h) {
(*node)->used = 1;
(*node)->down = malloc(sizeof(Node));
(*node)->down->parent = (*node);
(*node)->down->down = NULL;
(*node)->down->right = NULL;
(*node)->down->x = (*node)->x;
(*node)->down->y = (*node)->y + h;
(*node)->down->width = (*node)->width;
(*node)->down->height = (*node)->height - h;
(*node)->down->used = 0;
(*node)->right = malloc(sizeof(Node));
(*node)->right->parent = (*node);
(*node)->right->down = NULL;
(*node)->right->right = NULL;
(*node)->right->x = (*node)->x + w;
(*node)->right->y = (*node)->y;
(*node)->right->width = (*node)->width - w;
(*node)->right->height = (*node)->height;
(*node)->right->used = 0;
return *node;
}
int MAX(int a, int b) {
return (a > b) ? a : b;
}
int MIN(int a, int b) {
return (a < b) ? a : b;
}
void print2D(Node *root, int space)
{
// Base case
if (root == NULL)
return;
// Increase distance between levels
space += COUNT;
// Process right child first
print2D(root->right, space);
// Print current node after space
// count
printf("\n");
for (int i = COUNT; i < space; i++)
printf(" ");
printf("(w%d h%d)\n", root->width, root->height);
// Process left child
print2D(root->down, space);
}
**数字是左上角(有红点的位置)中每个块的坐标(x,y)。我这样做是为了更好地可视化不同的输出。
正如您在javascript输出图像中看到的那样,我绘制了红色轮廓,这是我的代码中最后3个块的位置,而在javascript中,它位于左侧,而错误。在我的代码中,这些块也应该放在左侧。
例如我代码中的最后一个块的坐标为408, 400
,而JavaScript中的最后一个块为50, 390
。
因为这是一棵二叉树,要对其进行调试,我做了一个显示它的函数,这就是我发现的结果:
在算法中,它是故意创建的,总是去rightNode
,然后去downNode
,但是我的代码却在错误的downNode
上进行节点。在javascript中,一切都按预期进行。
我已经这样做了好几天,而令我发疯的是,这些代码看起来相同,逻辑相同。那么,如果逻辑相同,为什么它不起作用? 我认为javascript高水平正在做我的C代码不做的事情...
已更改
Node * rightNode = findNode(root->right, w, h);
Node * downNode = findNode(root->down, w, h);
if (rightNode != NULL)
return rightNode;
return downNode;
到
Node * rightNode = findNode(root->right, w, h);
if (rightNode != NULL)
return rightNode;
Node * downNode = findNode(root->down, w, h);
return downNode;
但仍然存在相同的错误。
答案 0 :(得分:1)
我认为您的代码中有一个错误:
Node *findNode(Node *root, int w, int h) {
if (root->used == 1) {
Node * rightNode = findNode(root->right, w, h);
Node * downNode = findNode(root->right, w, h); //THIS LINE IS WRONG
if (rightNode != NULL)
return rightNode;
return findNode(root->down, w, h);
}
else if ((w <= root->width) && (h <= root->height)) {
return root;
}
else {
return NULL;
}
}
与原始JS相比,该行应为:
Node * downNode = findNode(root->down, w, h);
好的,既然上面的内容已经解决,这是另一种解决方法。
请参阅以下代码
Node *splitNode(Node **node, int w, int h) {
(*node)->used = 1;
(*node)->down = malloc(sizeof(Node));
(*node)->down->parent = (*node);
(*node)->down->down = NULL;
(*node)->down->right = NULL;
(*node)->down->x = (*node)->x;
(*node)->down->y = (*node)->y + h;
(*node)->down->width = (*node)->width;
(*node)->down->height = (*node)->height - h;
(*node)->down->used = 0;
(*node)->right = malloc(sizeof(Node));
(*node)->right->parent = (*node);
(*node)->right->down = NULL;
(*node)->right->right = NULL;
(*node)->right->x = (*node)->x + w;
(*node)->right->y = (*node)->y;
(*node)->right->width = (*node)->width - w;
(*node)->right->height = (*node)->height; //THIS LINE
(*node)->right->used = 0;
return *node;
}
请参见标记的行。 这应该是(我认为)
(*node)->right->height = h;
(JS已返回h:h
而不是h:node.h
)