HDU 5128 The E-pang Palace(2014广州赛区现场赛B题 计算几何)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5128
解题报告:在一个平面上给出n个点的坐标,用这n个点作为矩形的四个顶点,作两个矩形,要求两个矩形不能相交,也不能有边和点相交,然后两个矩形的面积之和要最大,求最大的面积之和是多少?如果不存在输出imp
因为n <=30,所以可以先把所有的矩形枚举出来,然后再暴力判断两两矩形组合,首先要满足位置关系,然后取面积和最大就是了.要注意的地方就是要小心一个大矩形包含一个小矩形的情况,在这种情况下,是满足位置关系的,但是,总面积只等于外面那个大矩形的面积.
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<cmath> 5 #include<algorithm> 6 #include<cmath> 7 using namespace std; 8 const double eps = 1e-9; 9 struct point 10 { 11 double x,y; 12 point(double x = 0,double y = 0): x(x),y(y) {} 13 friend point operator - (point a,point b) 14 { 15 return point(a.x-b.x,a.y-b.y); 16 } 17 }P[35]; 18 struct rect 19 { 20 point p[4]; 21 }R[1000]; 22 double dot(point a,point b) //叉积 23 { 24 return a.x*b.y - b.x * a.y; 25 } 26 int judge_pingxing(point a,point b) 27 { 28 return (fabs(dot(a,b)) < eps); 29 } 30 double dis(point a,point b) 31 { 32 return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); 33 } 34 int is_trang(point p1,point p2,point p3,point p4) //判断是不是矩形 35 { 36 point d1 = p1 - p2; 37 point d2 = p3 - p4; 38 if(judge_pingxing(d1,d2)) 39 { 40 if(p1.x > p2.x) swap(p1,p2); 41 if(p3.x > p4.x) swap(p3,p4); 42 d1 = p1-p2,d2 = p1-p3; 43 point d3 = p1 - p3,d4 = p2 - p4; 44 // printf("%.0lf %.0lf\n",d1.x,d1.y); 45 // printf("%.0lf %.0lf\n",d2.x,d2.y); 46 // printf("%.0lf\n",d1.x*d2.x+d1.y*d2.y); 47 if(fabs(d1.x*d2.x+d1.y*d2.y) < eps && judge_pingxing(d3,d4)) return 1; 48 } 49 return 0; 50 } 51 int make(int n) //构造矩形 52 { 53 int tot = 0; 54 for(int i = 0;i < n;++i) 55 for(int j = i+1;j < n;++j) 56 for(int k = j+1;k < n;++k) 57 for(int l = k+1;l < n;++l) 58 { 59 if(is_trang(P[i],P[j],P[k],P[l]) || is_trang(P[i],P[k],P[j],P[l])) 60 { 61 R[tot].p[0] = P[i]; 62 R[tot].p[1] = P[j]; 63 R[tot].p[2] = P[k]; 64 R[tot].p[3] = P[l]; 65 tot++; 66 } 67 } 68 return tot; 69 } 70 double Max(double a,double b) 71 { 72 return a > b? a:b; 73 } 74 int is_xj(point a1,point a2,point b1,point b2) 75 { 76 if(dot(b1-a1,a2-a1)*dot(b2-a1,a2-a1) < 0 || fabs(dot(b1-a1,a2-a1)*dot(b2-a1,a2-a1)) < eps) 77 if(dot(a1-b1,b2-b1)*dot(a2-b1,b2-b1) < 0 || fabs(dot(a1-b1,b2-b1)*dot(a2-b1,b2-b1)) < eps) 78 { 79 double m = dis(a1,b1); 80 m = Max(m,dis(a1,b2)); 81 m = Max(m,dis(a1,a2)); 82 m = Max(m,dis(a2,b1)); 83 m = Max(m,dis(a2,b2)); 84 m = Max(m,dis(b1,b2)); 85 if(fabs(dot(a1-a2,b1-b2))<eps && m > dis(a1,a2)+dis(b1,b2)) return 0; 86 return 1; 87 } 88 return 0; 89 } 90 struct node 91 { 92 point p[2]; 93 }rr1[4],rr2[4]; 94 int judge(rect a,rect b) 95 { 96 rr1[0].p[0] = a.p[0],rr1[0].p[1] = a.p[1]; 97 rr1[1].p[0] = a.p[0],rr1[1].p[1] = a.p[2]; 98 rr1[2].p[0] = a.p[2],rr1[2].p[1] = a.p[3]; 99 rr1[3].p[0] = a.p[1],rr1[3].p[1] = a.p[3]; 100 101 rr2[0].p[0] = b.p[0],rr2[0].p[1] = b.p[1]; 102 rr2[1].p[0] = b.p[0],rr2[1].p[1] = b.p[2]; 103 rr2[2].p[0] = b.p[1],rr2[2].p[1] = b.p[3]; 104 rr2[3].p[0] = b.p[2],rr2[3].p[1] = b.p[3]; 105 for(int i = 0;i < 4;++i) 106 for(int j = 0;j < 4;++j) 107 if(is_xj(rr1[i].p[0],rr1[i].p[1],rr2[j].p[0],rr2[j].p[1])) 108 return 0; 109 /* for(int i = 0;i < 4;++i) //只要枚举一个矩形的顶点是不是在另一个矩形里面或者边上 110 for(int j = i+1;j < 4;++j) 111 { 112 for(int k = 0;k < 4;++k) 113 for(int l = k+1;l < 4;++l) 114 { 115 if(is_xj(a.p[i],a.p[j],b.p[k],b.p[l])) 116 return 0; 117 } 118 }*/ 119 return 1; 120 } 121 122 bool cmp(point a,point b) 123 { 124 if(fabs(a.x-b.x) > eps) 125 return a.x < b.x; 126 else return a.y < b.y; 127 } 128 double get_area(rect a) 129 { 130 return dis(a.p[0],a.p[1]) * dis(a.p[0],a.p[2]); 131 } 132 int judge_in(rect a,rect b) 133 { 134 int flag = 0; 135 for(int i = 0;i < 4;++i) 136 { 137 if((a.p[i].x > b.p[0].x && a.p[i].x < b.p[2].x)) flag++; 138 if((a.p[i].y > b.p[0].y && a.p[i].y < b.p[1].y)) flag++; 139 } 140 return flag >= 8; 141 } 142 143 int main() 144 { 145 //printf("%d\n",is_trang(point(0,0),point(1,0),point(1,1),point(0,1))); 146 // freopen("in","r",stdin); 147 int n; 148 while(scanf("%d",&n),n) 149 { 150 for(int i = 0;i < n;++i) 151 scanf("%lf%lf",&P[i].x,&P[i].y); 152 sort(P,P+n,cmp); 153 int tot = make(n); //构造tot个矩形 154 double Max_ans = 0; 155 for(int i = 0;i < tot;++i) 156 sort(R[i].p,R[i].p+4,cmp); 157 // printf("tot = %d\n",tot); 158 for(int i = 0;i < tot;++i) 159 { 160 // for(int j = 0;j < 4;++j) 161 // printf("%.0lf %.0lf ",R[i].p[j].x,R[i].p[j].y); 162 // puts(""); 163 } 164 // printf("dlfjksdklj = %d\n",judge_in(R[1],R[0])); 165 for(int i = 0;i < tot;++i) 166 for(int j = i;j < tot;++j) 167 if(judge(R[i],R [j])) //满足位置关系 ,注意一个矩形包含另一个矩形的情况 168 { 169 double t = get_area(R[i]) + get_area(R[j]); //求两个矩形的面积 170 if(judge_in(R[i],R[j]) || judge_in(R[j],R[i])) Max_ans = Max(Max_ans,Max(get_area(R[i]),get_area(R[j]))); 171 else Max_ans = Max(Max_ans,t); 172 } 173 if(tot <= 0 || fabs(Max_ans) < eps) printf("imp\n"); 174 else printf("%.0lf\n",Max_ans+eps); 175 } 176 return 0; 177 }