|
要将凸包多边形a优化为外接四边形b,需要找到a的四个顶点,也就是距离凸包中心最远的点。具体实现可以采用旋转卡壳算法,该算法的主要思想是在凸包上选择一条边,然后将其与凸包上的其它边依次进行配对,以此得到凸包上任意两个点间的距离,并找到距离最大的两个点。这样就可以得到一个外接矩形,其四个顶点就是凸包中距离最远的四个点。
- #include <iostream>
- #include <algorithm>
- #include <cmath>
- using namespace std;
- struct Point{
- double x, y;
- };
- double cross(Point a, Point b, Point c){
- return (b.x-a.x)*(c.y-a.y) - (b.y-a.y)*(c.x-a.x);
- }
- double dist(Point a, Point b){
- return sqrt((b.x-a.x)*(b.x-a.x) + (b.y-a.y)*(b.y-a.y));
- }
- void rotating采用calipers(Point p[], int n, Point res[]){
- int j = 1, k = 1;
- for(int i=0; i<n; i++){
- while(cross(p[i], p[(i+1)%n], p[j]) > cross(p[i], p[(i+1)%n], p[(j+1)%n])){
- j = (j+1)%n;
- }
- while(dist(p[i], p[k]) < dist(p[i], p[(k+1)%n])){
- k = (k+1)%n;
- }
- if(i==0) res = p[i];
- if(i==n-1) res = p[i];
- if(dist(p[i], p[j]) > dist(res, res)){
- res = p[i];
- res = p[j];
- }
- if(cross(p[(i+1)%n], p[i], p[k]) > cross(p[(i+1)%n], p[i], p[(k+1)%n])){
- while(cross(p[(i+1)%n], p[i], p[k]) > cross(p[(i+1)%n], p[i], p[(k+1)%n])){
- k = (k+1)%n;
- }
- if(dist(p[i], p[k]) > dist(res, res)){
- res = p[k];
- }
- if(dist(p[j], p[(k+1)%n]) > dist(res, res)){
- res = p[(k+1)%n];
- }
- }
- else{
- while(cross(p[(i+1)%n], p[i], p[j]) < cross(p[(i+1)%n], p[i], p[(j+1)%n])){
- j = (j+1)%n;
- }
- if(dist(p[j], p[i]) > dist(res, res)){
- res = p[j];
- }
- if(dist(p[k], p[(j+1)%n]) > dist(res, res)){
- res = p[(j+1)%n];
- }
- }
- }
- }
- int main(){
- int n;
- cin >> n;
- Point* p = new Point[n];
- for(int i=0; i<n; i++){
- cin >> p[i].x >> p[i].y;
- }
- sort(p, p+n, [](Point a, Point b){
- return a.x < b.x || (a.x==b.x && a.y < b.y);
- });
- Point* res = new Point;
- rotating采用calipers(p, n, res);
- cout << "The four vertices of the optimized rectangle are: " << endl;
- for(int i=0; i<4; i++){
- cout << "(" << res[i].x << ", " << res[i].y << ")" << endl;
- }
- delete[] p;
- delete[] res;
- return 0;
- }
复制代码 |
|