一道算法题-求三个矩形的交集矩形。

给定矩形的定义如下:

struct Rect{
    int x; //表示矩形的左上水平坐标
    int y; //表示矩形的左上垂直坐标
    int w; //表示矩形宽度
    int h; //表示矩形高度
};

现在给三个矩形,求三个矩形的交集,如果没有交集,那么矩形的x,y,w和h均赋值为-1。例如下面示例图,求出三个矩形相交的粗线线框表示的矩形。

解题思路: 
解题思路很重要,没有集体思路,题目肯定是做出不来的。下面给出本人的解题思路: 
(1)判断三个矩形有没有交集。这个是难点,该怎么做呢?可以在x轴方向将三个矩形按x的大小从左到右排列,判断两两矩形在x轴方向是否有交集,如果有任意一对没有相交那么三个矩形没有交集。判断方法是如果rectB.x>=rectA.x+rectA.w的话,那么说明rectA和rectB之间没有交集。

同理,在y轴方向做同样的判断;

(2)求出任意两个矩形的交集矩形,再将交集矩形与第三个矩形再求交集,可得最后的交集矩形。

有了正确和清晰的思路,就可以写代码了,下面给出本人的实现,可供网友参考。

 1 #include <iostream>
 2 using namespace std;
 3 #include <vector>
 4 #include <algorithm>
 5 
 6 struct Rect{
 7     int x; //表示矩形的左上水平坐标
 8     int y; //表示矩形的左上垂直坐标
 9     int w; //表示矩形宽度
10     int h; //表示矩形高度
11 };
12 
13 //按照x递增排序
14 bool compareX(const Rect& rectA,const Rect& rectB ){
15     return rectA.x<rectB.x;
16 }
17 
18 //按照y递增排序
19 bool compareY(const Rect& rectA,const Rect& rectB ){
20     return rectA.y<rectB.y;
21 }
22 
23 //判断三个矩形是否相交
24 bool isIntersect(const Rect& rectA,const Rect& rectB,const Rect& rectC){
25     Rect rectLeft,rectXMid,rectRight; //从左向右的矩形
26     Rect rectTop,rectYMid,rectBelow;  //从上到下的矩形
27 
28     //将矩形按照x由左向右排序
29     vector<const Rect> vec;
30     vec.push_back(rectA);
31     vec.push_back(rectB);
32     vec.push_back(rectC);
33     sort(vec.begin(),vec.end(),compareX);
34     rectLeft=vec[0],rectXMid=vec[1],rectRight=vec[2];
35 
36     //水平方向任意两个矩形没有交集
37     if(rectXMid.x>=rectLeft.x+rectLeft.w||rectRight.x>=rectXMid.x+rectXMid.w||rectRight.x>=rectLeft.x+rectLeft.w)
38         return false;
39 
40     //同理将矩形按照y由上往下排序
41     sort(vec.begin(),vec.end(),compareY);
42     rectTop=vec[0],rectYMid=vec[1],rectBelow=vec[2];
43 
44     //垂直方向任意两个矩形没有交集
45     if(rectYMid.y>=rectTop.y+rectTop.h||rectBelow.y>=rectYMid.y+rectYMid.h||rectBelow.y>=rectTop.y+rectTop.h)
46         return false;
47     return true; //三个矩形有交集
48 }
49 
50 //两个矩形的交集,前提是两个矩形一定有交集
51 Rect intersection(const Rect& rectA,const Rect& rectB){
52     Rect resRect;
53     resRect.x=rectA.x>rectB.x?rectA.x:rectB.x; //选最右边的矩形的x作为交集的x
54     resRect.y=rectA.y>rectB.y?rectA.y:rectB.y; //选最下面的矩形的y作为交集的y
55     //选择左边矩形(x坐标较小者)的右边的作为交集矩形的右边,这样就可以求出交集矩形的宽度
56     resRect.w=rectA.x+rectA.w<rectB.x+rectB.w?rectA.x+rectA.w-resRect.x:rectB.x+rectB.w-resRect.x;
57     //同理,选择上面矩形(y坐标较小者)的下边的作为交集矩形的下边,这样就可以求出交集矩形的高度
58     resRect.h=rectA.y+rectA.h<rectB.y+rectB.y?rectA.y+rectA.h-resRect.y:rectB.y+rectB.h-resRect.y;
59     return resRect;
60 }
61 
62 
63 //求三个矩形的交集
64 Rect threeIntersection(const Rect& rectA,const Rect& rectB,const Rect& rectC){
65     Rect res;
66     bool isIntersectBool=isIntersect(rectA,rectB,rectC);
67     if(isIntersectBool){ //有相交
68         Rect rectAB=intersection(rectA,rectB);
69         res=intersection(rectAB,rectC);
70     }
71     else
72         res.x=res.y=res.w=res.h=-1;
73     return res;
74 }

测试结果如下:

int main(){
    Rect rectA,rectB,rectC;
    //测试案例1
    //rectA.x=0,rectA.y=0,rectA.w=1,rectA.h=1;
    //rectB.x=1,rectB.y=1,rectB.w=1,rectB.h=1;
    //rectC.x=2,rectC.y=2,rectC.w=1,rectC.h=1;

    //测试案例2
    rectA.x=0,rectA.y=0,rectA.w=2,rectA.h=2;
    rectB.x=1,rectB.y=1,rectB.w=1,rectB.h=1;
    rectC.x=1,rectC.y=1,rectC.w=1,rectC.h=1;

    Rect resRect=threeIntersection(rectA,rectB,rectC);
    if(resRect.x!=-1){ //有相交
        cout<<"resRect.x:"<<resRect.x<<endl;
        cout<<"resRect.y:"<<resRect.x<<endl;
        cout<<"resRect.w:"<<resRect.x<<endl;
        cout<<"resRect.h:"<<resRect.x<<endl;
    }
    else
        cout<<"not intersect"<<endl;
    getchar();
}

测试案例1输出:not intersect; 
测试案例2输出: 
resRect.x:1 
resRect.y:1 
resRect.w:1 
resRect.h:1

posted @ 2018-01-22 23:25  ~君莫笑~  阅读(1712)  评论(0编辑  收藏  举报