LA 4728 (旋转卡壳) Squares
题意:
求平面上的最远点对距离的平方。
分析:
对于这个数据量枚举肯定是要超时的。
首先这两个点一定是在凸包上的,所以可以枚举凸包上的点,因为凸包上的点要比原来的点会少很多,可最坏情况下的时间复杂度也是O(n2).
于是就有了旋转卡壳。
可以想象有两条平行直线紧紧地夹住这个凸包,那直线上的点就是对踵点对。对踵点对最多有四对,就是当凸包的两边和两直线重合的情况。
直线的角度不断变化,直线上的对踵点对也会发生变化,当直线旋转过180°后,那么凸包上所有的对踵点对也就全部遍历到了。
代码中还有很详细的注释。
里面是利用比较△(u, u+1, v) 和 △(u, u+1, v+1)的面积大小来寻找对踵点对的。因为是凸多边形,所以面积的比较转化成了两个叉积的比较,最后化简成了一个叉积PuPu+1×PvPv+1。
直接从化简出来的结果来看,如果两个向量的叉乘大于0的话,说明v正在远离直线PuPu+1,如果小于0的话说明正在靠近直线,也很容易理解。
//#define LOCAL
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std; struct Point
{
int x, y;
Point(int x=, int y=):x(x), y(y){}
};
typedef Point Vector; Point operator + (Point a, Point b) { return Point(a.x+b.x, a.y+b.y); }
Point operator - (Point a, Point b) { return Point(a.x-b.x, a.y-b.y); }
int Dot(Vector A, Vector B) { return A.x*B.x + A.y*B.y; }
int Cross(Vector A, Vector B) { return A.x*B.y - A.y*B.x; } bool operator < (const Point& a, const Point& b)
{
return a.x < b.x || (a.x == b.x && a.y < b.y);
} bool operator == (const Point& a, const Point& b)
{
return a.x == b.x && a.y == b.x;
} int Dist2(const Point& a, const Point& b)
{ return (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y); } vector<Point> ConvexHull(vector<Point>& p)
{
sort(p.begin(), p.end());
p.erase(unique(p.begin(), p.end()), p.end()); int n = p.size();
int m = ;
vector<Point> ch(n+);
for(int i = ; i < n; ++i)
{
while(m > && Cross(ch[m-]-ch[m-], p[i]-ch[m-]) <= ) m--;
ch[m++] = p[i];
}
int k = m;
for(int i = n-; i >= ; --i)
{
while(m > k && Cross(ch[m-]-ch[m-], p[i]-ch[m-]) <= ) m--;
ch[m++] = p[i];
}
if(n > ) m--;
ch.resize(m);
return ch;
} int diameter2(vector<Point>& points)
{
vector<Point> p = ConvexHull(points);
int n = p.size();
//for(int i = 0; i < n; ++i) printf("%d %d\n", p[i].x, p[i].y);
if(n == ) return ;
if(n == ) return Dist2(p[], p[]);
p.push_back(p[]);
int ans = ;
for(int u = , v = ; u < n; ++u)
{// 一条直线贴住边p[u]-p[u+1]
while(true)
{
// 当Area(p[u], p[u+1], p[v+1]) <= Area(p[u], p[u+1], p[v])时停止旋转
//因为两个三角形有一公共边,所以面积大的那个点到直线距离大
// 即Cross(p[u+1]-p[u], p[v+1]-p[u]) - Cross(p[u+1]-p[u], p[v]-p[u]) <= 0
// 根据Cross(A,B) - Cross(A,C) = Cross(A,B-C)
// 化简得Cross(p[u+1]-p[u], p[v+1]-p[v]) <= 0
int diff = Cross(p[u+]-p[u], p[v+]-p[v]);
if(diff <= )
{
ans = max(ans, Dist2(p[u], p[v]));
if(diff == ) ans = max(ans, Dist2(p[u], p[v+]));
break;
}
v = (v+)%n;
}
}
return ans;
} int main(void)
{
#ifdef LOCAL
freopen("4728in.txt", "r", stdin);
#endif int T;
scanf("%d", &T);
while(T--)
{
int n, x, y, w;
scanf("%d", &n);
vector<Point> p;
for(int i = ; i < n; ++i)
{
scanf("%d%d%d", &x, &y, &w);
p.push_back(Point(x, y));
p.push_back(Point(x+w, y));
p.push_back(Point(x+w, y+w));
p.push_back(Point(x, y+w));
}
printf("%d\n", diameter2(p));
} return ;
}
代码君
LA 4728 (旋转卡壳) Squares的更多相关文章
- LA 4728 旋转卡壳算法求凸包的最大直径
#include<iostream> #include<cstdio> #include<cmath> #include<vector> #includ ...
- UVAL 4728 Squares(旋转卡壳)
Squares [题目链接]Squares [题目类型]旋转卡壳 &题解: 听着算法名字,感觉挺难,仔细一看之后,发现其实很简单,就是依靠所构成三角行面积来快速的找对踵点,就可以省去很多的复杂 ...
- UVALive 4728 Squares(旋转卡壳)
Squares The famous Korean IT company plans to make a digital map of the Earth with help of wireless ...
- UVA 4728 Squares(凸包+旋转卡壳)
题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=17267 [思路] 凸包+旋转卡壳 求出凸包,用旋转卡壳算出凸包的直 ...
- UVa 1453 - Squares 旋转卡壳求凸包直径
旋转卡壳求凸包直径. 参考:http://www.cppblog.com/staryjy/archive/2010/09/25/101412.html #include <cstdio> ...
- 1393: Robert Hood 旋转卡壳 凸包
http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1393 http://poj.org/problem?id=2187 Beauty Contest ...
- POJ 3608 Bridge Across Islands --凸包间距离,旋转卡壳
题意: 给你两个凸包,求其最短距离. 解法: POJ 我真的是弄不懂了,也不说一声点就是按顺时针给出的,不用调整点顺序. 还是说数据水了,没出乱给点或给逆时针点的数据呢..我直接默认顺时针给的点居然A ...
- 【BZOJ 1069】【SCOI 2007】最大土地面积 凸包+旋转卡壳
因为凸壳上对踵点的单调性所以旋转卡壳线性绕一圈就可以啦啦啦--- 先求凸包,然后旋转卡壳记录$sum1$和$sum2$,最后统计答案就可以了 #include<cmath> #includ ...
- 【POJ 2187】Beauty Contest(凸包直径、旋转卡壳)
给定点集的最远两点的距离. 先用graham求凸包.旋(xuán)转(zhuàn)卡(qiǎ)壳(ké)求凸包直径. ps:旋转卡壳算法的典型运用 http://blog.csdn.net/hanch ...
随机推荐
- 备份apt目录节省下载时间
备份与清理 * 备份快速设置已下载的部分软件包,以便重装系统再次使用,免去重新下载的时间 tar cizvf backup.tar.gz /var/cache/apt/archives ...
- 2876: [Noi2012]骑行川藏 - BZOJ
Description 蛋蛋非常热衷于挑战自我,今年暑假他准备沿川藏线骑着自行车从成都前往拉萨.川藏线的沿途有着非常美丽的风景,但在这一路上也有着很多的艰难险阻,路况变化多端,而蛋蛋的体力十分有限,因 ...
- 【IOC--Common Service Locator】不依赖于某个具体的IoC
你在你的应用程序应用IoC容器了吗,你是否希望不依赖于某个具体的IoC,微软的模式与实践团队在Codeplex上发布的Common Service Locator.Common Service Loc ...
- httpsClient抓取证书
在执行webservice的过程中,出现如下异常: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorExcep ...
- 关于prototype以及继承方面的理解
学习笔记(致 渐悟) 写在前面的话 今天看<javascript高级程序设计>的时候,看到有关继承和原型链prototype时遇到些疑问,特回来研究下,同时也感谢JS群网友"渐悟 ...
- jstl表达式使用方法
1.jstl.jar servlet.jar支持 2.jsp引入标签库 <%@ taglib prefix="c" uri="http://java.sun.co ...
- POJ3080Blue Jeans
http://poj.org/problem?id=3080 题意 : 给你几个DNA序列,让你找他们的共同的最长的子串,若是子串长度小于3,就输出no significant commonaliti ...
- POJ 2240 Arbitrage(floyd)
http://poj.org/problem?id=2240 题意 : 好吧,又是一个换钱的题:套利是利用货币汇率的差异进行的货币转换,例如用1美元购买0.5英镑,1英镑可以购买10法郎,一法郎可以购 ...
- Android 加载时在actionBar右上角添加一个加载图标
①首先要在Activity的 setContentView()方法前调用requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); // ...
- 03 - 运行OCCI测试程序遇到0xc0150002错误
通过控制面板->管理工具->Event Viewer->Windows Log->Application Logs, 可以看到可以看到是如下错误 “C:\Windows\ora ...