点击这里查看原题
旋转卡壳模板题,建议看这里的讲解
旋转卡壳的代码只比凸包多几行,非常好写。
/*
User:Small
Language:C++
Problem No.:2187
*/
#include<stdio.h>
#include<iostream>
#include<iomanip>
#include<string.h>
#include<algorithm>
#include<queue>
#include<stack>
#include<math.h>
#define ll long long
#define inf 999999999
using namespace std;
const int M=5e4+5;
int n,s[M],tp,k;
int ans;
struct no{
int x,y;
}p[M];
void init(){
memset(s,0,sizeof(s));
tp=k=0;
}
int dis(no a,no b){
return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}
int cross(no a,no b,no c){
no u=(no){b.x-a.x,b.y-a.y},v=(no){c.x-a.x,c.y-a.y};
return u.x*v.y-u.y*v.x;
}
bool cmp(no a,no b){
int tmp=cross(p[0],a,b);
if(tmp==0) return dis(p[0],a)<dis(p[0],b);
return tmp>0;
}
void graham(){
for(int i=0;i<n;i++){
while(tp>1&&cross(p[s[tp-2]],p[s[tp-1]],p[i])<=0) tp--;
s[tp++]=i;
}
}
void rc(){
int i=0,j=1;
s[tp]=s[0];
ans=dis(p[s[i]],p[s[i+1]]);
for(i=0;i<tp;i++){
while(abs(cross(p[s[i+1]],p[s[j+1]],p[s[i]]))>abs(cross(p[s[i+1]],p[s[j]],p[s[i]]))) j=(j+1)%tp;//找到距离p[s[i]],p[s[i+1]]两点连线最远的点j
ans=max(ans,max(dis(p[s[i]],p[s[j]]),dis(p[s[i+1]],p[s[j+1]])));//既要算dis(p[s[i]],p[s[j]])也要算dis(p[s[i+1]],p[s[j+1]]),因为可能会出现两线平行的情况
}
}
void solve(){
init();
for(int i=0;i<n;i++){
cin>>p[i].x>>p[i].y;
if(p[i].x<p[k].x||(p[i].x==p[k].x&&p[i].y<p[k].y)) k=i;
}
swap(p[k],p[0]);
sort(p+1,p+n,cmp);
graham();
rc();
cout<<ans<<endl;
}
int main(){
freopen("data.in","r",stdin);//
ios::sync_with_stdio(false);
while(cin>>n&&n) solve();
return 0;
}

本文介绍了一道关于旋转卡壳的算法题目,并提供了详细的代码实现。旋转卡壳算法是在凸包基础上的一种拓展,用于求解特定几何问题。文章通过一个具体的示例展示了如何使用C++来实现该算法。
460

被折叠的 条评论
为什么被折叠?



