簡體   English   中英

如何找出最大的矩形是否包含其他較小的矩形

[英]How to find out whether the largest rectangle contains other smaller rectangles

我必須創建一個程序來生成 3 個隨機矩形,並使用左上角點和右下角點的坐標找到每個矩形的面積(坐標是隨機的,介於 (-50;50) 之間。

問題是它必須確定最大的矩形並指示其他兩個/一個是否位於其中,如果不是 - 顯示相應的消息。

這不是重疊,其他矩形/矩形必須完全在最大的一個中。

這是我已經做過的:

#include <stdio.h> 
#include <locale>

struct Point {
    int x;
    int y;
};

struct Rectangle {
    struct Point topLeft;
    struct Point botRight;
};

int Area(struct Rectangle r) {
    int length, breadth;
    length = r.botRight.x - r.topLeft.x;
    breadth = r.topLeft.y - r.botRight.y;

    return length * breadth;
}

int main() {
    srand(time(NULL));

    struct Rectangle r1, r2, r3;
    
    r1.topLeft.x  = -50 + rand() % 50;
    r1.topLeft.y  = -50 + rand() % 50;
    r1.botRight.x = -50 + rand() % 50;
    r1.botRight.y = -50 + rand() % 50;

    while (r1.botRight.x <= r1.topLeft.x) {
        r1.botRight.x = -50 + rand() % 50;
    }
    while (r1.topLeft.y <= r1.botRight.y) {
        r1.topLeft.y = -50 + rand() % 50;
    }
    printf("\t----------RECTANGLE 1----------\n");
    printf("\tTop left point is x = %d y = %d\n", r1.topLeft.x, r1.topLeft.y);
    printf("\tBottom right point is x = %d y = %d\n", r1.botRight.x, r1.botRight.y);
    printf("\tArea is %d\n", Area(r1));
    
    r2.topLeft.x  = -50 + rand() % 50;
    r2.topLeft.y  = -50 + rand() % 50;
    r2.botRight.x = -50 + rand() % 50;
    r2.botRight.y = -50 + rand() % 50;

    while (r2.botRight.x <= r2.topLeft.x) {
        r2.botRight.x = -50 + rand() % 50;
    }
    while (r2.topLeft.y <= r2.botRight.y) {
        r2.topLeft.y = -50 + rand() % 50;
    }
    printf("\t----------RECTANGLE 2----------\n");
    printf("\tTop left point is x = %d y = %d\n", r2.topLeft.x, r2.topLeft.y);
    printf("\tBottom right point is x = %d y = %d\n", r2.botRight.x, r2.botRight.y);
    printf("\tArea is %d\n", Area(r2));
    
    r3.topLeft.x = -50 + rand() % 50;
    r3.topLeft.y = -50 + rand() % 50;
    r3.botRight.x = -50 + rand() % 50;
    r3.botRight.y = -50 + rand() % 50;

    while (r3.botRight.x <= r3.topLeft.x) {
        r3.botRight.x = -50 + rand() % 50;
    }
    while (r3.topLeft.y <= r3.botRight.y) {
        r3.topLeft.y = -50 + rand() % 50;
    }
    printf("\t----------RECTANGLE 3----------\n");
    printf("\tTop left point is x = %d y = %d\n", r3.topLeft.x, r3.topLeft.y);
    printf("\tBottom right point is x = %d y = %d\n", r3.botRight.x, r3.botRight.y);
    printf("\tArea is %d\n\n", Area(r3));
    
    if (Area(r1) >= Area(r2) && Area(r1) >= Area(r3))
        printf("\tRECTANGLE 1 HAS A BIGGEST AREA --> %d\n", Area(r1));
    
    if (Area(r2) >= Area(r1) && Area(r2) >= Area(r3))
        printf("\tRECTANGLE 2 HAS A BIGGEST AREA --> %d\n", Area(r2));

    if (Area(r3) >= Area(r1) && Area(r3) >= Area(r2))
        printf("\tRECTANGLE 3 HAS A BIGGEST AREA --> %d\n", Area(r3));
}

首先,您需要一個矩形數組並按面積對它們進行排序:

struct Rectangle rects[N];

//return:
//- negative value, if a < b
//- zero,           if a == b
//- positive value, if a > b
int rect_cmp(const void *a, const void *b)
{
    return Area(*((struct Rectangle*)a)) - Area(*((struct Rectangle*)b));
}

//use qsort: https://en.cppreference.com/w/c/algorithm/qsort
qsort(rects, N, sizeof(struct Rectangle), rect_cmp);

數組rects現在將包含所有矩形,按升序排列,從最低到最高區域。

從現在開始,您所要做的就是遍歷數組並測試最大的矩形是否包含以下后續矩形。 以下代碼選擇最大的矩形並遍歷所有后續矩形以測試它們是否在內部。 然后挑出第二大的再做一次測試,以此類推,eg

for (int i=N-1; i >= 0; --i) { //current largest rectangle
    for (int j=i-1; j >= 0; --j) { //test if the next rectangles in sequence are inside
        if (contains(rects[i], rects[j])) {
            //rect[j] inside rect[i]
        } else {
            //rect[j] not inside rect[i]
        }
    }
}

一個可能的結果是第一個 rect 既不包含第二個 rect 也不包含第三個 rect,但第二個 rect 可能包含第三個 rect。

第 1 項:
確實沒有必要使用point結構。 這個問題很簡單,只需跟蹤 x 的 2 個值和 y 的 2 個值。 當我們這樣做時,也可以存儲每個矩形的面積。

typedef struct {
    int x0, x1, y0, y1, area;
} Rect;

請注意,名稱x0x1沒有偏差 試圖控制哪個坐標對是“左上”,哪個是“右下”是很困難的。 矩形有兩條水平邊(重要的是它們不相等)。 僅存儲y的較低值和較高值。 同樣,只存儲垂直邊x的“左和右”值……這讓事情變得簡單。

第 2 項:
如果可能的話,思考和編碼時不要直接關注負數是值得的。

const int wid = 101; // for -50 to +50
const int hgt = 101; // for -50 to +50

第 3 項:
通過復制/粘貼代碼生成 3 組值表明這應該在調用 3 次的 function 中完成。 (假設下一個作業是“對 20 個矩形執行相同的操作。”)

下面包括兩個額外的“無分支”函數,它們返回兩個 integer 值的最小值或最大值。

int min( int x, int y ) { return y ^ ((x^y) & -(x<y)); }
int max( int x, int y ) { return y ^ ((x^y) & -(x>y)); }

void genRect( Rect *r ) {
    int v0 = rand() % wid; // A random horizontal value (a vertical line)
    int v1 = ( v0 + 1 + rand()%(wid-3) ) % wid; // A different horizontal value

    r->x0 = min( v0, v1 ); // the lower of the two values
    r->x1 = max( v0, v1 ); // and the higher

    // do the same for horizontal edges (vertical boundaries)
    v0 = rand() % hgt;
    v1 = ( r->y0 + 1 + rand()%(hgt-3) ) % hgt;

    r->y0 = min( v0, v1 );
    r->y1 = max( v0, v1 );

    // calc and store the area, too
    r->area = (r->x1 - r->x0) * (r->y1 - r->y0);
}

需要注意的重要一點是,x 和 y 的第二個值的計算永遠不會與第一個值相同。 OP 代碼有可能在右邊界生成一個“左邊緣”,然后進入一個無限循環,試圖生成一個總是被拒絕的值。

正如另一個答案中所建議的,現在很容易對小數組進行qsort() (大矩形可能包含較小的矩形)。

通過將 x0 與 x0 和 x1 與 x1 進行比較,在另一個內部搜索一個要簡單得多……(對於 y 維度也是如此)。

因為代碼一直在處理 (0,0) 到 (100,100)(含),所以 output 是根據任務進行調整的地方。

void print( int n, Rect *r ) {
    printf( "Rect %d: BotLft(%d,%d) TopRgt(%d, %d) Area %d\n",
        n, r->x0 - 50, r->y0 - 50, r->x1 - 50, r->y1 - 50, r->area );
}

我把它作為練習留給讀者,以消除上面的任意常量。

最后,確定一個較小矩形的 xy 邊界是否完全落在較大矩形的 xy 邊界內是一個簡單的練習。 帶有 4 個條件的單個if()語句就足夠了。


PS:我完成了代碼,跑了幾次。 只是通過增加候選矩形的數量,幸運的是較大的確實包含較小的。 只有 3 個矩形的樣本大小將需要大量迭代才能偶然地在另一個矩形中定義一個......

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM