#include <stdio.h>
#include <stdlib.h>
/**
* @brief Find largest rectangle for a new window in a canvas with some existing windows.
* @param width Canvas width in pixel
* @param height Canvas height in pixel
* @param objects Existing objects, in the form {{x_topleft,y_topleft,x_bottomright_y_bottomright},...}
* @param num_objects Number of objects in previous parameter
* @param output Array to store result as {x_topleft,y_topleft,x_bottomright_y_bottomright}
*/
void find_largest_rect(int width, int height, int (*objects)[4],
int num_objects, int* output) {
// create canvas array
unsigned char* canvas
= (unsigned char*)malloc(width
* height
* sizeof( unsigned char));
int* up
= (int*)malloc(width
* sizeof(int)); int* up_last
= (int*)malloc(width
* sizeof(int)); int* left
= (int*)malloc(width
* sizeof(int)); int* left_last
= (int*)malloc(width
* sizeof(int)); int* right
= (int*)malloc(width
* sizeof(int)); int* right_last
= (int*)malloc(width
* sizeof(int)); int ans = 0, lo = 0, ro = 0;
int x1 = 0, y1 = 0, x2 = 0, y2 = 0;
int i = 0, j = 0, k = 0;
// set whole canvas to 1
for (i = 0; i < height; i++)
for (j = 0; j < width; j++) {
canvas[i * (width) + j] = 1;
}
// initialize temp vars
for (j = 0; j < width; j++) {
up[j] = 0;
up_last[j] = 0;
left[j] = 0;
left_last[j] = 0;
right[j] = 0;
right_last[j] = 0;
}
// set occupied points to 0
for (i = 0; i < num_objects; i++) {
x1 = objects[i][0];
y1 = objects[i][1];
x2 = objects[i][2];
y2 = objects[i][3];
// boundary check
x1 = x1 < 0 ? 0 : (x1 > width ? width : x1);
y1 = y1 < 0 ? 0 : (y1 > height ? height : y1);
x2 = x2 < 0 ? 0 : (x2 > width ? width : x2);
y2 = y2 < 0 ? 0 : (y2 > height ? height : y2);
for (j = y1; j <= y2; j++) {
for (k = x1; k <= x2; k++) {
canvas[j * (width) + k] = 0;
}
}
}
x1 = 0, y1 = 0, x2 = 0, y2 = 0;
for (i = 0; i < height; i++) {
lo = -1;
ro = width;
// store last temp vars
for (j = 0; j < width; j++) {
up_last[j] = up[j];
left_last[j] = left[j];
right_last[j] = right[j];
}
// initialize up[] and left[] for current i
for (j = 0; j < width; j++) {
if (canvas[i * width + j] == 0) {
left[j] = up[j] = 0;
lo = j;
}
else {
up[j] = (i == 0) ? 1 : up_last[j] + 1;
left[j] = (i == 0) ? lo + 1 : ((left_last[j] > lo + 1) ?
left_last[j] : lo + 1);
}
}
for (j = width - 1; j >= 0; j--) {
if (canvas[i * width + j] == 0) {
right[j] = width;
ro = j;
}
else {
right[j] = (i == 0) ? ro - 1 : ((right_last[j] < ro - 1) ?
right_last[j] : ro - 1);
}
if (up[j] * (right[j] - left[j] + 1) > ans) {
ans = up[j] * (right[j] - left[j] + 1);
x1 = left[j];
y1 = i - up[j] + 1;
x2 = j;
y2 = i;
}
}
}
output[0] = x1;
output[1] = y1;
output[2] = x2;
output[3] = y2;
printf("Max rectangle area = %d\n", ans
);
// print canvas
// for (i = 0; i < height; i++) {
// printf("%d\t", i);
// for (j = 0; j < width; j++) {
// printf("%d", *(canvas + i * (width) + j));
// }
// printf("\n");
// }
}
int main(void) {
//canvas properties
int width = 30;
int height = 20;
// objects in canvas
int num_objects = 3;
int objects[3][4] = {{0, 0, 9, 9}, {20, 0, 29, 19}, {5, 14, 14, 18}};
// var to store result coordinates of topleft and bottomright vertices (x1,y1,x2,y2)
int output[4] = {0, 0, 0, 0};
find_largest_rect(width, height, objects, num_objects, output);
printf("(%d,%d)->(%d,%d)\n", output
[0], output
[1], output
[2], output
[3]);
return 0;
}
I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KCi8qKgogKiBAYnJpZWYgRmluZCBsYXJnZXN0IHJlY3RhbmdsZSBmb3IgYSBuZXcgd2luZG93IGluIGEgY2FudmFzIHdpdGggc29tZSBleGlzdGluZyB3aW5kb3dzLgogKiBAcGFyYW0gd2lkdGggQ2FudmFzIHdpZHRoIGluIHBpeGVsCiAqIEBwYXJhbSBoZWlnaHQgQ2FudmFzIGhlaWdodCBpbiBwaXhlbAogKiBAcGFyYW0gb2JqZWN0cyBFeGlzdGluZyBvYmplY3RzLCBpbiB0aGUgZm9ybSB7e3hfdG9wbGVmdCx5X3RvcGxlZnQseF9ib3R0b21yaWdodF95X2JvdHRvbXJpZ2h0fSwuLi59CiAqIEBwYXJhbSBudW1fb2JqZWN0cyBOdW1iZXIgb2Ygb2JqZWN0cyBpbiBwcmV2aW91cyBwYXJhbWV0ZXIKICogQHBhcmFtIG91dHB1dCBBcnJheSB0byBzdG9yZSByZXN1bHQgYXMge3hfdG9wbGVmdCx5X3RvcGxlZnQseF9ib3R0b21yaWdodF95X2JvdHRvbXJpZ2h0fQogKi8Kdm9pZCBmaW5kX2xhcmdlc3RfcmVjdChpbnQgd2lkdGgsIGludCBoZWlnaHQsIGludCAoKm9iamVjdHMpWzRdLAogICAgICAgICAgICAgICAgICAgICAgIGludCBudW1fb2JqZWN0cywgaW50KiBvdXRwdXQpIHsKICAgIC8vIGNyZWF0ZSBjYW52YXMgYXJyYXkKICAgIHVuc2lnbmVkIGNoYXIqIGNhbnZhcyA9ICh1bnNpZ25lZCBjaGFyKiltYWxsb2Mod2lkdGggKiBoZWlnaHQgKiBzaXplb2YoCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5zaWduZWQgY2hhcikpOwogICAgaW50KiB1cCAgICAgICAgID0gKGludCopbWFsbG9jKHdpZHRoICogc2l6ZW9mKGludCkpOwogICAgaW50KiB1cF9sYXN0ICAgID0gKGludCopbWFsbG9jKHdpZHRoICogc2l6ZW9mKGludCkpOwogICAgaW50KiBsZWZ0ICAgICAgID0gKGludCopbWFsbG9jKHdpZHRoICogc2l6ZW9mKGludCkpOwogICAgaW50KiBsZWZ0X2xhc3QgID0gKGludCopbWFsbG9jKHdpZHRoICogc2l6ZW9mKGludCkpOwogICAgaW50KiByaWdodCAgICAgID0gKGludCopbWFsbG9jKHdpZHRoICogc2l6ZW9mKGludCkpOwogICAgaW50KiByaWdodF9sYXN0ID0gKGludCopbWFsbG9jKHdpZHRoICogc2l6ZW9mKGludCkpOwogICAgaW50IGFucyA9IDAsIGxvID0gMCwgcm8gPSAwOwogICAgaW50IHgxID0gMCwgeTEgPSAwLCB4MiA9IDAsIHkyID0gMDsKICAgIGludCBpID0gMCwgaiA9IDAsIGsgPSAwOwoKICAgIC8vIHNldCB3aG9sZSBjYW52YXMgdG8gMQogICAgZm9yIChpID0gMDsgaSA8IGhlaWdodDsgaSsrKQogICAgICAgIGZvciAoaiA9IDA7IGogPCB3aWR0aDsgaisrKSB7CiAgICAgICAgICAgIGNhbnZhc1tpICogKHdpZHRoKSArIGpdID0gMTsKICAgICAgICB9CgogICAgLy8gaW5pdGlhbGl6ZSB0ZW1wIHZhcnMKICAgIGZvciAoaiA9IDA7IGogPCB3aWR0aDsgaisrKSB7CiAgICAgICAgdXBbal0gPSAwOwogICAgICAgIHVwX2xhc3Rbal0gPSAwOwogICAgICAgIGxlZnRbal0gPSAwOwogICAgICAgIGxlZnRfbGFzdFtqXSA9IDA7CiAgICAgICAgcmlnaHRbal0gPSAwOwogICAgICAgIHJpZ2h0X2xhc3Rbal0gPSAwOwogICAgfQoKICAgIC8vIHNldCBvY2N1cGllZCBwb2ludHMgdG8gMAogICAgZm9yIChpID0gMDsgaSA8IG51bV9vYmplY3RzOyBpKyspIHsKICAgICAgICB4MSA9IG9iamVjdHNbaV1bMF07CiAgICAgICAgeTEgPSBvYmplY3RzW2ldWzFdOwogICAgICAgIHgyID0gb2JqZWN0c1tpXVsyXTsKICAgICAgICB5MiA9IG9iamVjdHNbaV1bM107CgogICAgICAgIC8vIGJvdW5kYXJ5IGNoZWNrCiAgICAgICAgeDEgPSB4MSA8IDAgPyAwIDogKHgxID4gd2lkdGggPyB3aWR0aCA6IHgxKTsKICAgICAgICB5MSA9IHkxIDwgMCA/IDAgOiAoeTEgPiBoZWlnaHQgPyBoZWlnaHQgOiB5MSk7CiAgICAgICAgeDIgPSB4MiA8IDAgPyAwIDogKHgyID4gd2lkdGggPyB3aWR0aCA6IHgyKTsKICAgICAgICB5MiA9IHkyIDwgMCA/IDAgOiAoeTIgPiBoZWlnaHQgPyBoZWlnaHQgOiB5Mik7CgogICAgICAgIGZvciAoaiA9IHkxOyBqIDw9IHkyOyBqKyspIHsKICAgICAgICAgICAgZm9yIChrID0geDE7IGsgPD0geDI7IGsrKykgewogICAgICAgICAgICAgICAgY2FudmFzW2ogKiAod2lkdGgpICsga10gPSAwOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgIHgxID0gMCwgeTEgPSAwLCB4MiA9IDAsIHkyID0gMDsKCiAgICBmb3IgKGkgPSAwOyBpIDwgaGVpZ2h0OyBpKyspIHsKICAgICAgICBsbyA9IC0xOwogICAgICAgIHJvID0gd2lkdGg7CgogICAgICAgIC8vIHN0b3JlIGxhc3QgdGVtcCB2YXJzCiAgICAgICAgZm9yIChqID0gMDsgaiA8IHdpZHRoOyBqKyspIHsKICAgICAgICAgICAgdXBfbGFzdFtqXSA9IHVwW2pdOwogICAgICAgICAgICBsZWZ0X2xhc3Rbal0gPSBsZWZ0W2pdOwogICAgICAgICAgICByaWdodF9sYXN0W2pdID0gcmlnaHRbal07CiAgICAgICAgfQoKICAgICAgICAvLyBpbml0aWFsaXplIHVwW10gYW5kIGxlZnRbXSBmb3IgY3VycmVudCBpCiAgICAgICAgZm9yIChqID0gMDsgaiA8IHdpZHRoOyBqKyspIHsKICAgICAgICAgICAgaWYgKGNhbnZhc1tpICogd2lkdGggKyBqXSA9PSAwKSB7CiAgICAgICAgICAgICAgICBsZWZ0W2pdID0gdXBbal0gPSAwOwogICAgICAgICAgICAgICAgbG8gPSBqOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgdXBbal0gPSAoaSA9PSAwKSA/IDEgOiB1cF9sYXN0W2pdICsgMTsKICAgICAgICAgICAgICAgIGxlZnRbal0gPSAoaSA9PSAwKSA/IGxvICsgMSA6ICgobGVmdF9sYXN0W2pdID4gbG8gKyAxKSA/CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVmdF9sYXN0W2pdIDogbG8gKyAxKTsKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgZm9yIChqID0gd2lkdGggLSAxOyBqID49IDA7IGotLSkgewogICAgICAgICAgICBpZiAoY2FudmFzW2kgKiB3aWR0aCArIGpdID09IDApIHsKICAgICAgICAgICAgICAgIHJpZ2h0W2pdID0gd2lkdGg7CiAgICAgICAgICAgICAgICBybyA9IGo7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICByaWdodFtqXSA9IChpID09IDApID8gcm8gLSAxIDogKChyaWdodF9sYXN0W2pdIDwgcm8gLSAxKSA/CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJpZ2h0X2xhc3Rbal0gOiBybyAtIDEpOwogICAgICAgICAgICB9CgogICAgICAgICAgICBpZiAodXBbal0gKiAocmlnaHRbal0gLSBsZWZ0W2pdICsgMSkgPiBhbnMpIHsKICAgICAgICAgICAgICAgIGFucyA9IHVwW2pdICogKHJpZ2h0W2pdIC0gbGVmdFtqXSArIDEpOwogICAgICAgICAgICAgICAgeDEgPSBsZWZ0W2pdOwogICAgICAgICAgICAgICAgeTEgPSBpIC0gdXBbal0gKyAxOwogICAgICAgICAgICAgICAgeDIgPSBqOwogICAgICAgICAgICAgICAgeTIgPSBpOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgIG91dHB1dFswXSA9IHgxOwogICAgb3V0cHV0WzFdID0geTE7CiAgICBvdXRwdXRbMl0gPSB4MjsKICAgIG91dHB1dFszXSA9IHkyOwoKICAgIHByaW50ZigiTWF4IHJlY3RhbmdsZSBhcmVhID0gJWRcbiIsIGFucyk7CgogICAgLy8gcHJpbnQgY2FudmFzCiAgICAvLyAgICBmb3IgKGkgPSAwOyBpIDwgaGVpZ2h0OyBpKyspIHsKICAgIC8vICAgICAgICBwcmludGYoIiVkXHQiLCBpKTsKCiAgICAvLyAgICAgICAgZm9yIChqID0gMDsgaiA8IHdpZHRoOyBqKyspIHsKICAgIC8vICAgICAgICAgICAgcHJpbnRmKCIlZCIsICooY2FudmFzICsgaSAqICh3aWR0aCkgKyBqKSk7CiAgICAvLyAgICAgICAgfQoKICAgIC8vICAgICAgICBwcmludGYoIlxuIik7CiAgICAvLyAgICB9CgogICAgZnJlZShjYW52YXMpOwogICAgZnJlZSh1cCk7CiAgICBmcmVlKHVwX2xhc3QpOwogICAgZnJlZShsZWZ0KTsKICAgIGZyZWUobGVmdF9sYXN0KTsKICAgIGZyZWUocmlnaHQpOwogICAgZnJlZShyaWdodF9sYXN0KTsKfQoKaW50IG1haW4odm9pZCkgewogICAgLy9jYW52YXMgcHJvcGVydGllcwogICAgaW50IHdpZHRoID0gMzA7CiAgICBpbnQgaGVpZ2h0ID0gMjA7CgogICAgLy8gb2JqZWN0cyBpbiBjYW52YXMKICAgIGludCBudW1fb2JqZWN0cyA9IDM7CiAgICBpbnQgb2JqZWN0c1szXVs0XSA9IHt7MCwgMCwgOSwgOX0sIHsyMCwgMCwgMjksIDE5fSwgezUsIDE0LCAxNCwgMTh9fTsKCiAgICAvLyB2YXIgdG8gc3RvcmUgcmVzdWx0IGNvb3JkaW5hdGVzIG9mIHRvcGxlZnQgYW5kIGJvdHRvbXJpZ2h0IHZlcnRpY2VzICh4MSx5MSx4Mix5MikKICAgIGludCBvdXRwdXRbNF0gPSB7MCwgMCwgMCwgMH07CgogICAgZmluZF9sYXJnZXN0X3JlY3Qod2lkdGgsIGhlaWdodCwgb2JqZWN0cywgbnVtX29iamVjdHMsIG91dHB1dCk7CgogICAgcHJpbnRmKCIoJWQsJWQpLT4oJWQsJWQpXG4iLCBvdXRwdXRbMF0sIG91dHB1dFsxXSwgb3V0cHV0WzJdLCBvdXRwdXRbM10pOwoKICAgIHJldHVybiAwOwp9Cg==