题意:

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

分析:

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

首先这两个点一定是在凸包上的,所以可以枚举凸包上的点,因为凸包上的点要比原来的点会少很多,可最坏情况下的时间复杂度也是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=, int y=):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 = ;
  41. vector<Point> ch(n+);
  42. for(int i = ; i < n; ++i)
  43. {
  44. while(m > && Cross(ch[m-]-ch[m-], p[i]-ch[m-]) <= ) m--;
  45. ch[m++] = p[i];
  46. }
  47. int k = m;
  48. for(int i = n-; i >= ; --i)
  49. {
  50. while(m > k && Cross(ch[m-]-ch[m-], p[i]-ch[m-]) <= ) m--;
  51. ch[m++] = p[i];
  52. }
  53. if(n > ) 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 == ) return ;
  64. if(n == ) return Dist2(p[], p[]);
  65. p.push_back(p[]);
  66. int ans = ;
  67. for(int u = , v = ; 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+]-p[u], p[v+]-p[v]);
  77. if(diff <= )
  78. {
  79. ans = max(ans, Dist2(p[u], p[v]));
  80. if(diff == ) ans = max(ans, Dist2(p[u], p[v+]));
  81. break;
  82. }
  83. v = (v+)%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 = ; 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 ;
  114. }

代码君

LA 4728 (旋转卡壳) Squares的更多相关文章

  1. LA 4728 旋转卡壳算法求凸包的最大直径

    #include<iostream> #include<cstdio> #include<cmath> #include<vector> #includ ...

  2. UVAL 4728 Squares(旋转卡壳)

    Squares [题目链接]Squares [题目类型]旋转卡壳 &题解: 听着算法名字,感觉挺难,仔细一看之后,发现其实很简单,就是依靠所构成三角行面积来快速的找对踵点,就可以省去很多的复杂 ...

  3. UVALive 4728 Squares(旋转卡壳)

    Squares The famous Korean IT company  plans to make a digital map of the Earth with help of wireless ...

  4. UVA 4728 Squares(凸包+旋转卡壳)

    题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=17267 [思路] 凸包+旋转卡壳 求出凸包,用旋转卡壳算出凸包的直 ...

  5. UVa 1453 - Squares 旋转卡壳求凸包直径

    旋转卡壳求凸包直径. 参考:http://www.cppblog.com/staryjy/archive/2010/09/25/101412.html #include <cstdio> ...

  6. 1393: Robert Hood 旋转卡壳 凸包

    http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1393 http://poj.org/problem?id=2187 Beauty Contest ...

  7. POJ 3608 Bridge Across Islands --凸包间距离,旋转卡壳

    题意: 给你两个凸包,求其最短距离. 解法: POJ 我真的是弄不懂了,也不说一声点就是按顺时针给出的,不用调整点顺序. 还是说数据水了,没出乱给点或给逆时针点的数据呢..我直接默认顺时针给的点居然A ...

  8. 【BZOJ 1069】【SCOI 2007】最大土地面积 凸包+旋转卡壳

    因为凸壳上对踵点的单调性所以旋转卡壳线性绕一圈就可以啦啦啦--- 先求凸包,然后旋转卡壳记录$sum1$和$sum2$,最后统计答案就可以了 #include<cmath> #includ ...

  9. 【POJ 2187】Beauty Contest(凸包直径、旋转卡壳)

    给定点集的最远两点的距离. 先用graham求凸包.旋(xuán)转(zhuàn)卡(qiǎ)壳(ké)求凸包直径. ps:旋转卡壳算法的典型运用 http://blog.csdn.net/hanch ...

随机推荐

  1. asp.net asp:TextBox控件绑定值后,获取不到新值问题解决方法

    把Page_Load里绑定的代码放在    if(!IsPostBack){}里面后,即可获取到更新的值. 意思为第一次加载执行.

  2. mongodb 的安装历程

    mongo 安装历程 mongo的安装方法有千万种,只有一种让我觉得还不错,说说安装过程中的一点心德. 方法一:源码安装,千万别用这种方法,尼马我用虚拟机编译了一下午,竟然没有编译完,强制关机,第二天 ...

  3. iOS开发之数据存取3-CoreData自定义数据类型

    当系统提供的类型不能达到我们的使用要求时,比如我想在CoreData中存储UIColor,该怎么办呢? 这时候就要用到CoreData中非常强大的一个存储类型了:Transformable 下面将通过 ...

  4. Windows 进程通信 之 DDE技术

    DDE (Dynamic Data Exchange,DDE)动态数据交换,是一种进程间通信机制,它最早是随着Windows由微软提出的.当前大部分软件仍旧支持DDE,但最近十年里微软已经停止发展DD ...

  5. uva 11029

    看了别人的解法 发现了 modf 这个函数 取小数部分 /*********************************************************************** ...

  6. Web App之一

    JSP/HTML/CSS---------View(不包含任何的数据,只作为基本的layout) JS------------------------Data(update JSP/HTML)

  7. java split函数 对空的处理

    String str = "5,6,55,66,,,,@"; String[] chk_deep = str.split("@"); System.out.pr ...

  8. Lua 的数据结构

    1. Arrays: 注意 #(data), # 加上 table名字 == size of data = {}; , do --行 , do --列 data[(y-)*+x] = (y-)*+x; ...

  9. mac上eclipse上运行word count

    1.打开eclipse之后,建立wordcount项目 package wordcount; import java.io.IOException; import java.util.StringTo ...

  10. java基础知识回顾之java Thread类学习(十)--线程的状态以及转化使用的方法介绍

       线程的概述:         线程是程序的多个执行路径,执行调度的单位,依托于进程存在.线程不仅可以共享进程的内存,而且还拥有一个属于自己的内存空间,这段内存空间叫做线程栈,是建立线程的时候由系 ...