题目
http://www.lydsy.com/JudgeOnline/problem.php?id=1069
题解
我的第一道旋转卡壳。一开始WA,但就是查不出错来,最后直接套用了我以前的模板(求凸包部分),A了。
其实很水,就是先求一下凸包,然后枚举矩形的对角线,另外两个点旋转卡壳一下就行了。
代码
//凸包、旋转卡壳
#include <cstdio>
#include <algorithm>
#include <cmath>
#define eps 10e-7
#define maxn 3000
using namespace std;
struct vec
{
double x, y;
double operator*(vec v){return x*v.y-v.x*y;}
vec operator-(vec v){return (vec){x-v.x,y-v.y};}
}p[maxn], s[maxn];
int N, top, next[maxn];
double S;
bool operator<(vec v1, vec v2)
{
v1=v1-s[1],v2=v2-s[1];
return v1*v2==0?v1.x*v1.x+v1.y*v1.y<v2.x*v2.x+v2.y*v2.y:v1*v2>0;
}
void graham()
{
int i, j;
vec v1, v2, t;
for(j=1,i=2;i<=N;i++)
if(p[i].y<p[j].y or p[i].y==p[j].y and p[i].x<p[j].x)j=i;
t=p[j],p[j]=p[1],p[1]=t;
s[top=1]=t;
sort(p+2,p+N+1);
for(i=2;i<=N;i++)
{
while(top>1 and (p[i]-s[top])*(s[top]-s[top-1])>-eps)top--;
s[++top]=p[i];
}
}
double area(vec p1, vec p2, vec p3)
{return abs((p2-p1)*(p3-p1))/2;}
void qiake()
{
int a, b, p, q, i;
for(i=1;i<top;i++)next[i]=i+1;next[top]=1;
for(a=1;a<=top-3;a++)
{
p=a+1,q=a+3;
for(b=a+2;b<=top;b++)
{
while(area(s[a],s[b],s[next[p]])>area(s[a],s[b],s[p]))p=next[p];
while(area(s[a],s[b],s[next[q]])>area(s[a],s[b],s[q]))q=next[q];
S=max(S,area(s[a],s[b],s[p])+area(s[a],s[b],s[q]));
}
}
}
int main()
{
int i;
scanf("%d",&N);
for(i=1;i<=N;i++)scanf("%lf%lf",&p[i].x,&p[i].y);
graham();
qiake();
printf("%.3lf\n",S);
return 0;
}