POJ 2187 Beauty Contest 旋转卡壳
http://poj.org/problem?id=2187
旋转卡壳的思想并不难,你就想象是两个平行直线夹住凸包...求的就是夹住的两个对锺点...
这题更容易了...求出所有对锺点以后直接一遍扫过去求最大点距就行了...
用的是一个结论: s[i],s[i+1],s[q] 构成的三角形只要面积最大<s[i],s[q]> 和 <s[i+1],s[q]>就一定是对锺点对
接下来根据观察...按逆时针枚举所有边的时候q的位置一定是逆时针移动...所以我们根据上一点q的位置逆时针枚举点即可...
找凸包O(nlogn) , 第一遍找q O(n) , 之后旋转操作 O(n) , 总共的复杂度O(nlogn)
提醒一下这题很坑...必须处理 只有2个点,共线,共点的情况,如果是用一般的凸包模板肯定WA...稍微修改一下就行...
/********************* Template ************************/ #include <set> #include <map> #include <list> #include <cmath> #include <ctime> #include <deque> #include <queue> #include <stack> #include <bitset> #include <cstdio> #include <string> #include <vector> #include <cassert> #include <cstdlib> #include <cstring> #include <sstream> #include <fstream> #include <numeric> #include <iomanip> #include <iostream> #include <algorithm> #include <functional> using namespace std; #define EPS 1e-8 #define MAXN 100005 #define MOD (int)1e9+7 #define PI acos(-1.0) #define INF ((1LL)<<50) #define max(a,b) ((a) > (b) ? (a) : (b)) #define min(a,b) ((a) < (b) ? (a) : (b)) #define max3(a,b,c) (max(max(a,b),c)) #define min3(a,b,c) (min(min(a,b),c)) #define BUG cout<<"BUG! "<<endl #define LINE cout<<"------------------"<<endl #define L(t) (t << 1) #define R(t) (t << 1 | 1) #define Mid(a,b) ((a + b) >> 1) #define lowbit(a) (a & -a) #define FIN freopen("in.txt","r",stdin) #pragma comment (linker,"/STACK:102400000,102400000") // typedef long long LL; // typedef unsigned long long ULL; // typedef __int64 LL; // typedef unisigned __int64 ULL; // int gcd(int a,int b){ return b?gcd(b,a%b):a; } // int lcm(int a,int b){ return a*b/gcd(a,b); } /********************* F ************************/ struct POINT{ double x,y; POINT(double _x = 0, double _y = 0):x(_x),y(_y){}; }; POINT p[MAXN],s[MAXN]; double dist(POINT p1,POINT p2){ return((p1.x-p2.x) * (p1.x-p2.x) + (p1.y-p2.y) * (p1.y-p2.y)); } double multiply(POINT sp,POINT ep,POINT op){ return (sp.x-op.x) * (ep.y-op.y) - (ep.x-op.x) * (sp.y-op.y); } bool ptcmp(POINT a,POINT b){ // 极角排序cmp p[]为全局变量 if(multiply(a,b,p[0]) == 0) return dist(p[0],a) < dist(p[0],b); return (multiply(a,b,p[0]) > 0); } int Graham_scan(POINT p[],POINT s[],int n){ // 返回凸包点的个数(修改版处理共线,无凸包) int i,k = 0,top = 2; for(i = 1; i < n ; i++) // 取y最小且x最小的点为凸包起点 if((p[i].y < p[k].y) || ((p[i].y == p[k].y) && (p[i].x < p[k].x))) k = i; swap(p[0],p[k]); // 起点设置为p[0] if(n == 2) { // 只有两个点不构成凸包的特判 s[0] = p[0]; s[1] = p[1]; return 2; } sort(p+1,p+n,ptcmp); // 极角排序 for(i = 0 ; i < 3 ; i++) s[i] = p[i]; // 前三个点入栈 while(multiply(s[0],s[top],s[top-1]) == 0 && i < n){ // 前三个点的共线特判 s[top-1] = s[top]; s[top] = p[i++]; } if(i == n){ //所有点都共线的特判 s[1] = s[top]; return 2; } for(; i < n ; i++){ while(multiply(p[i],s[top],s[top-1]) >= 0) top--; s[++top] = p[i]; } return top + 1; } double Triangle_area(POINT a,POINT b,POINT c){ return fabs(multiply(a,b,c)/2); } double Rotation_Calipers(int len){ //旋转卡壳求凸包最大点距 double ans = 0; for(int i = 0 ,q = 1; i < len ; i++){ while(Triangle_area(s[i],s[(i+1)%len],s[(q+1)%len]) > Triangle_area(s[i],s[(i+1)%len],s[q])){ q = (q + 1) % len; } ans = max3(ans,dist(s[q],s[i]),dist(s[q],s[(i+1)%len])); } return ans; } int main() { //freopen("in.txt","r",stdin); //freopen("ou.txt","w",stdout); int a,b,n; double r; while(~scanf("%d",&n)){ for(int i = 0 ; i < n ; i++) scanf("%lf%lf",&p[i].x,&p[i].y); int len = Graham_scan(p,s,n); double ans = Rotation_Calipers(len); printf("%.0lf\n",ans); } return 0; }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步