算法練習之矩形的交集與並集的計算


這是一道競賽的題目,如下:

在編寫圖形界面軟件的時候,經常會遇到處理兩個矩形的關系。

如圖【1.jpg】所示,矩形的交集指的是:兩個矩形重疊區的矩形,當然也可能不存在(參看【2.jpg】)。兩個矩形的並集指的是:能包含這兩個矩形的最小矩形,它一定是存在的。

           

本題目的要求就是:由用戶輸入兩個矩形的坐標,程序輸出它們的交集和並集矩形。

矩形坐標的輸入格式是輸入兩個對角點坐標,注意,不保證是哪個對角,也不保證順序(你可以體會一下,在桌面上拖動鼠標拉矩形,4個方向都可以的)。

輸入數據格式:
x1,y1,x2,y2
x1,y1,x2,y2

數據共兩行,每行表示一個矩形。每行是兩個點的坐標。x坐標在左,y坐標在右。坐標系統是:屏幕左上角為(0,0),x坐標水平向右增大;y坐標垂直向下增大。

要求程序輸出格式:
x1,y1,長度,高度
x1,y1,長度,高度

也是兩行數據,分別表示交集和並集。如果交集不存在,則輸出“不存在”

前邊兩項是左上角的坐標。后邊是矩形的長度和高度。

例如,用戶輸入:
100,220,300,100
150,150,300,300

則程序輸出:
150,150,150,70
100,100,200,200

例如,用戶輸入:
10,10,20,20
30,30,40,40

則程序輸出:
不存在
10,10,30,30

 

題目給人的第一感覺並不是很難,但可能繁瑣~~

我的第一種想法就是先求“並集矩形”因為這個會很好求,那用什么數據結構來表示呢?

顯然,保存矩形的四個頂點咯,用一個Point類來保存:

 

class Point {
    int x;
    int y;
}

 

但,仔細想一想,實際上我們並不需要太多的數據!

 我們要確定一個矩形,只需要矩形的起始x坐標、結束x坐標、起始y坐標和結束y坐標。文字不好說,看圖吧:

 所以,保存一個矩形類我們可以這樣寫:

class Rect {
    public int startX;
    public int endX;
    public int startY;
    public int endY;
}

 

題目中,x1,y1和x2,y2這兩個點並不一定是從左上角到右下角這兩個點,但一定是對角線上的!所以根據大小關系還是很好確定的:

public Rect(String str) {
    String[] l = str.split(",");
    int x1 = Integer.parseInt(l[0]);
    int y1 = Integer.parseInt(l[1]);
    int x2 = Integer.parseInt(l[2]);
    int y2 = Integer.parseInt(l[3]);
    startX = x1 < x2 ? x1 : x2;
    endX = x1 > x2 ? x1 : x2;
    startY = y1 < y2 ? y1 : y2;
    endY = y1 > y2 ? y1 : y2;
}

 

一個可以從字符串直接生成矩形的構造方法~~~。

 

從上圖不難看出,“並集矩形”的startX是由矩形1和矩形2的startX中比較小的那個來決定的,endX由比較大的endX決定。所以,“並集矩形”的求法就很簡單了:

// 由兩個矩形構造出他們的“並集矩形”
public Rect(Rect r1, Rect r2) {
    startX = r1.startX < r2.startX ? r1.startX : r2.startX;
    endX = r1.endX > r2.endX ? r1.endX : r2.endX;
    startY = r1.startY < r2.startY ? r1.startY : r2.startY;
    endY = r1.endY > r2.endY ? r1.endY : r2.endY;
}

 

“交集矩形”貌似就麻煩多了,有幾種情況要進行判斷。

觀察圖中的紅色框,可以得到一個簡單的結論:“交集矩形”的startX由較大的startX決定、endX由較小的endX決定,Y也是同樣的情況。

但是,對於沒有交集的情況呢?

我們用上面的方法進行推導,“交集矩形”的startX就是藍色矩形的startX,endX就是綠色矩形的endX。顯然,startX大於endX。這樣的矩形應該是不存在的。對於Y軸應該也是同樣的情況。

找到了規律求解也就不難了,所有代碼如下:

public class Test {
    public static void main(String[] args) {
        Rect r1 = new Rect("100,220,300,100");
        Rect r2 = new Rect("150,150,300,300");
        Rect merge = new Rect(r1, r2);
        Rect both = Rect.getBothArea(r1, r2);
        both.printInfo();
        merge.printInfo();
        System.out.println("~~~~~~~~~~~~~~~~~~~~~~");
        r1 = new Rect("10,10,20,20");
        r2 = new Rect("30,30,40,40");
        merge = new Rect(r1, r2);
        both = Rect.getBothArea(r1, r2);
        both.printInfo();
        merge.printInfo();
    }
}

class Rect {
    public int startX;
    public int endX;
    public int startY;
    public int endY;

    public Rect() {
    }

    // 由兩個矩形構造出他們的“並集矩形”
    public Rect(Rect r1, Rect r2) {
        startX = r1.startX < r2.startX ? r1.startX : r2.startX;
        endX = r1.endX > r2.endX ? r1.endX : r2.endX;
        startY = r1.startY < r2.startY ? r1.startY : r2.startY;
        endY = r1.endY > r2.endY ? r1.endY : r2.endY;
    }

    public static Rect getBothArea(Rect r1, Rect r2) {
        Rect merge = new Rect(r1, r2);
        Rect both = new Rect();
        both.startX = r1.startX == merge.startX ? r2.startX : r1.startX;
        both.endX = r1.endX == merge.endX ? r2.endX : r1.endX;
        both.startY = r1.startY == merge.startY ? r2.startY : r1.startY;
        both.endY = r1.endY == merge.endY ? r2.endY : r1.endY;
        return both;
    }

    public Rect(String str) {
        String[] l = str.split(",");
        int x1 = Integer.parseInt(l[0]);
        int y1 = Integer.parseInt(l[1]);
        int x2 = Integer.parseInt(l[2]);
        int y2 = Integer.parseInt(l[3]);
        startX = x1 < x2 ? x1 : x2;
        endX = x1 > x2 ? x1 : x2;
        startY = y1 < y2 ? y1 : y2;
        endY = y1 > y2 ? y1 : y2;
    }

    public void printInfo() {
        if (startX >= endX || startY >= endY) {
            System.out.println("不存在");
        } else {
            System.out.println(startX + "," + startY + "," + (endX - startX) + ","
                    + (endY - startY));
        }
    }
}

 

代碼比想象中的少得多了~~~

后記:一開始先分析題目,找出解題的突破口比一上來就蠻干要強得多!記得自己第一次做這題就是沒仔細思考,用四個Point來保存矩形,最后,關系太多,把自己給繞暈了~~~

 

yjiyjige 2013.4.20

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM