题意:

求平面上的最远点对距离的平方。

分析:

对于这个数据量枚举肯定是要超时的。

首先这两个点一定是在凸包上的,所以可以枚举凸包上的点,因为凸包上的点要比原来的点会少很多,可最坏情况下的时间复杂度也是O(n2).

于是就有了旋转卡壳。

可以想象有两条平行直线紧紧地夹住这个凸包,那直线上的点就是对踵点对。对踵点对最多有四对,就是当凸包的两边和两直线重合的情况。

直线的角度不断变化,直线上的对踵点对也会发生变化,当直线旋转过180°后,那么凸包上所有的对踵点对也就全部遍历到了。

代码中还有很详细的注释。

里面是利用比较△(u, u+1, v) 和 △(u, u+1, v+1)的面积大小来寻找对踵点对的。因为是凸多边形,所以面积的比较转化成了两个叉积的比较,最后化简成了一个叉积PuPu+1×PvPv+1

直接从化简出来的结果来看,如果两个向量的叉乘大于0的话,说明v正在远离直线PuPu+1,如果小于0的话说明正在靠近直线,也很容易理解。

  1 //#define LOCAL
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #include <cmath>
  6 #include <vector>
  7 using namespace std;
  8
  9 struct Point
 10 {
 11     int x, y;
 12     Point(int x=0, int y=0):x(x), y(y){}
 13 };
 14 typedef Point Vector;
 15
 16 Point operator + (Point a, Point b) { return Point(a.x+b.x, a.y+b.y); }
 17 Point operator - (Point a, Point b) { return Point(a.x-b.x, a.y-b.y); }
 18 int Dot(Vector A, Vector B) { return A.x*B.x + A.y*B.y; }
 19 int Cross(Vector A, Vector B) { return A.x*B.y - A.y*B.x; }
 20
 21 bool operator < (const Point& a, const Point& b)
 22 {
 23     return a.x < b.x || (a.x == b.x && a.y < b.y);
 24 }
 25
 26 bool operator == (const Point& a, const Point& b)
 27 {
 28     return a.x == b.x && a.y == b.x;
 29 }
 30
 31 int Dist2(const Point& a, const Point& b)
 32 { return (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y); }
 33
 34 vector<Point> ConvexHull(vector<Point>& p)
 35 {
 36     sort(p.begin(), p.end());
 37     p.erase(unique(p.begin(), p.end()), p.end());
 38
 39     int n = p.size();
 40     int m = 0;
 41     vector<Point> ch(n+1);
 42     for(int i = 0; i < n; ++i)
 43     {
 44         while(m > 1 && Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2]) <= 0) m--;
 45         ch[m++] = p[i];
 46     }
 47     int k = m;
 48     for(int i = n-2; i >= 0; --i)
 49     {
 50         while(m > k && Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2]) <= 0) m--;
 51         ch[m++] = p[i];
 52     }
 53     if(n > 1) m--;
 54     ch.resize(m);
 55     return ch;
 56 }
 57
 58 int diameter2(vector<Point>& points)
 59 {
 60     vector<Point> p = ConvexHull(points);
 61     int n = p.size();
 62     //for(int i = 0; i < n; ++i)    printf("%d %d\n", p[i].x, p[i].y);
 63     if(n == 1)    return 0;
 64     if(n == 2)  return Dist2(p[0], p[1]);
 65     p.push_back(p[0]);
 66     int ans = 0;
 67     for(int u = 0, v = 1; u < n; ++u)
 68     {// 一条直线贴住边p[u]-p[u+1]
 69         while(true)
 70         {
 71             // 当Area(p[u], p[u+1], p[v+1]) <= Area(p[u], p[u+1], p[v])时停止旋转
 72             //因为两个三角形有一公共边,所以面积大的那个点到直线距离大
 73             // 即Cross(p[u+1]-p[u], p[v+1]-p[u]) - Cross(p[u+1]-p[u], p[v]-p[u]) <= 0
 74             // 根据Cross(A,B) - Cross(A,C) = Cross(A,B-C)
 75             // 化简得Cross(p[u+1]-p[u], p[v+1]-p[v]) <= 0
 76             int diff = Cross(p[u+1]-p[u], p[v+1]-p[v]);
 77             if(diff <= 0)
 78             {
 79                 ans = max(ans, Dist2(p[u], p[v]));
 80                 if(diff == 0)    ans = max(ans, Dist2(p[u], p[v+1]));
 81                 break;
 82             }
 83             v = (v+1)%n;
 84         }
 85     }
 86     return ans;
 87 }
 88
 89 int main(void)
 90 {
 91     #ifdef LOCAL
 92         freopen("4728in.txt", "r", stdin);
 93     #endif
 94
 95     int T;
 96     scanf("%d", &T);
 97     while(T--)
 98     {
 99         int n, x, y, w;
100         scanf("%d", &n);
101         vector<Point> p;
102         for(int i = 0; i < n; ++i)
103         {
104             scanf("%d%d%d", &x, &y, &w);
105             p.push_back(Point(x, y));
106             p.push_back(Point(x+w, y));
107             p.push_back(Point(x+w, y+w));
108             p.push_back(Point(x, y+w));
109         }
110         printf("%d\n", diameter2(p));
111     }
112
113     return 0;
114 }

代码君

转载于:https://www.cnblogs.com/AOQNRMGYXLMV/p/4038684.html

LA 4728 (旋转卡壳) Squares相关推荐

  1. 【LA 4728】Square, Seoul 2009 (凸包,旋转卡壳)

    Description 给定很多个正方形的定点,求这些点中两两之间距离的最大值. Solution 直接求出凸包后旋转卡壳即可.. Source /************************** ...

  2. 算法复习——凸包加旋转卡壳(poj2187)

    题目: Description Bessie, Farmer John's prize cow, has just won first place in a bovine beauty contest ...

  3. Bridge Across Islands POJ - 3608 旋转卡壳求凸包最近距离

    \(\color{#0066ff}{题目描述}\) 几千年前,有一个小王国位于太平洋的中部.王国的领土由两个分离的岛屿组成.由于洋流的冲击,两个岛屿的形状都变成了凸多边形.王国的国王想建立一座桥来连接 ...

  4. BZOJ 1185: [HNOI2007]最小矩形覆盖 [旋转卡壳]

    1185: [HNOI2007]最小矩形覆盖 Time Limit: 10 Sec  Memory Limit: 162 MBSec  Special Judge Submit: 1435  Solv ...

  5. 算法学习:计算几何旋转卡壳

    [定义] [对踵点]多边形上存在平行切线的两点 [多边形半径]多边形上任意两点的最大长度 [旋转卡壳] 选取y轴上,最高和最低的两个点,令两条平行于x轴的线切过这两点 然后我们开始让这两条线旋转 当一 ...

  6. bzoj 1069 [SCOI2007]最大土地面积——旋转卡壳

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1069 发现 n 可以 n^2 .所以枚举对角线,分开的两部分三角形就可以旋转卡壳了. 注意坐 ...

  7. 【BZOJ1185】【HNOI2007】最小矩形覆盖(凸包+旋转卡壳)

    传送门 题意:求最小矩阵覆盖 有这样一个结论:矩阵一定有一条边在凸包上(不会证) 那可以枚举每条边 同时旋转卡壳 只是这时不只维护一个对踵点对,同时在左右侧再维护一个最远点 可以发现左右最远点一定是和 ...

  8. poj 2079(旋转卡壳)

    题意:求出平面内的点集所组成的面积最大的三角形. 解题思路:考虑凸包+旋转卡壳.面积最大的三角形的三点必定在凸包的顶点上,只不过这里要注意,三角形的边不一定就是凸包的边,有可能三角形相邻两点是横跨凸包 ...

  9. poj 2187 Beauty Contest (凸包: 最远点对,最长直径 , 旋转卡壳法)

    http://poj.org/problem?id=2187 题意: 最长的点对近距离的平方: 题解: 旋转卡壳法, 要注意的地方是,有 所有点共线的情况,所以,(求凸包时)要将,共线点去出 :    ...

最新文章

  1. 乘“云原生”之风、踏“数字化”的浪,《新程序员003》开启预售!
  2. Java设计模式—模板方法模式
  3. HDU-2037-今年暑假不AC
  4. adb devices指令实例讲解
  5. Swoole 自定义项目初始化事件处理的实现
  6. 在Linux系统下实现进程,Linux进程学习(一)之Linux进程的基本知识和实现
  7. Matplotlib - bar(条形图)
  8. Cocos2d-x一张小背景重复贴图充满整个屏幕
  9. GPUImageMovieWriter录制视频问题
  10. Soft Bellman Equation and Soft Value Iteration证明
  11. linuxt gogs搭建
  12. Linux的顶级十六进制编辑器
  13. android反编译软件Mac,在Mac上进行安卓反编译
  14. 路由器忘记密码的解决办法
  15. 常用信号去噪与信号回归方法的原理及MATLAB实现
  16. 苹果悄悄在硅谷买楼 以古希腊诸神命名 据说跟造车有关
  17. 《Python编程快速上手——让繁琐的工作自动化》读书笔记4
  18. 对有序表的查找(快步搜索算法)
  19. FileOperatorWSInstaller.zip——上海一网通登录社保下载提示,却无法下载
  20. 载波 、基带信号、调制波、调频信号

热门文章

  1. Oracle 计划新的移动 OpenJDK 项目
  2. Fastlane为iOS带来持续部署
  3. UML类图(上):类、继承和实现
  4. 学习《html5.css3.0》网页布局和样式精粹(第一天)
  5. 执行文件mysql使用source 命令乱码问题
  6. 无线安全 - 802.1x 和 EAP 类型
  7. php 如何设置后台,phpcms怎么重新设置后台网址
  8. 快速上手Tomcat
  9. apache 2许可证_如何理解Apache 2专利许可
  10. 如何使用recordMyDesktop录制截屏视频