| ||||||||||
| Online Judge | Problem Set | Authors | Online Contests | User | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest | |||||||||
旋转卡壳(RC)是能过的,不过和暴力的区别不大……G++,暴力313ms,RC297ms,16ms完全可以算是看脸的问题……
200题AC了,第一次贴代码,各位贱笑了
#include<stdio.h>
#include<math.h>
#define eps 1e-7
#define MaxN 50001
struct Point
{
double x,y;
Point(double a=0,double b=0){x=a;y=b;}
};
typedef Point Vector;
Vector operator + (Point a,Point b)
{
return Vector(a.x+b.x,a.y+b.y);
}
Vector operator - (Point a,Point b)
{
return Vector(a.x-b.x,a.y-b.y);
}
Vector operator * (Point a,double k)
{
return Vector(a.x*k,a.y*k);
}
Vector operator / (Point a,double k)
{
return Vector(a.x/k,a.y/k);
}
inline double dis(Point &a,Point &b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
/*------Graham求凸包----*/
//得到sp-op和ep-op的叉积
//>0时ep在opsp的逆时针方向,<0时顺时针,=0时共线
inline double Cross(Point sp,Point ep,Point op)
{
return (sp.x-op.x)*(ep.y-op.y)-(ep.x-op.x)*(sp.y-op.y);
}
//两向量求叉积,求三角形面积需要除以2
double Cross(Vector a,Vector b)
{
return a.x*b.y-b.x*a.y;
}
inline int cmp(Point &a,Point &b)
{
if (a.y==b.y) return (a.x<b.x);
return (a.y<b.y);
}
//采用eps的精度判断大/小于零
inline int epssgn(double x)
{
if (fabs(x)<eps) return 0;
else return x<0?-1:1;
}
//对所有的点进行一次排序
void QSort(Point p[],int l,int r)
{
int i=l,j=r;
Point mid=p[(l+r)/2],swap;
while (i<=j)
{
while (cmp(p[i],mid)) i++;
while (cmp(mid,p[j])) j--;
if (i<=j)
{
swap=p[i];
p[i]=p[j];
p[j]=swap;
i++;j--;
}
}
if (i<r) QSort(p,i,r);
if (l<j) QSort(p,l,j);
}
//n为原图的点数,p[]为原图的点(0~n-1),top为凸包点的数量(0~top-1),res[]为凸包点的下标,。
int Graham(Point p[],int n,int res[])
{
int i,len,top;
top=1;
QSort(p,0,n-1);
for (i=0;i<3;i++) res[i]=i;
for (i=2;i<n;i++)
{
while (top && epssgn(Cross(p[i],p[res[top]],p[res[top-1]]))>=0) top--;
res[++top]=i;
}
len=top;
res[++top]=n-2;
for (i=n-3;i>=0;i--)
{
while (top!=len && epssgn(Cross(p[i], p[res[top]], p[res[top-1]]))>=0) top--;
res[++top]=i;
}
return top;
}
//旋转卡壳求凸包p[res[1~chnum]]的直径,对踵点数量appnum,存储在app[][2]中
double Diameter(Point p[],int res[],int chnum,int app[][2],int &appnum) //AntiPodal Point
{
int i,j;
double ret=0,nowlen;
res[chnum]=res[0];
j=1;
appnum=0;
for (i=0;i<chnum;i++)
{
while (Cross(p[res[i]]-p[res[i+1]],p[res[j+1]]-p[res[i+1]])
<Cross(p[res[i]]-p[res[i+1]],p[res[j]]-p[res[i+1]]))
{
j++;
j%=chnum;
}
app[appnum][0]=res[i];
app[appnum][1]=res[j];
appnum++;
nowlen=dis(p[res[i]],p[res[j]]);
if (nowlen>ret) ret=nowlen;
nowlen=dis(p[res[i+1]],p[res[j+1]]);
if (nowlen>ret) ret=nowlen;
}
return ret;
}
/*------Graham求凸包----*/
Point p[MaxN];
int res[MaxN];
int chnum;
int app[MaxN][2];
int main()
{
int i,n,appnum;
double ans;
//freopen("poj2187.txt","r",stdin);
//freopen("poj2187ans.txt","w",stdout);
while (scanf("%d",&n)!=EOF)
{
for (i=0;i<n;i++) scanf("%lf%lf",&p[i].x,&p[i].y);
if (n<3) printf("%.f\n",dis(p[0],p[1])*dis(p[0],p[1]));
else
{
chnum=Graham(p,n,res);
ans=Diameter(p,res,chnum,app,appnum);
/*旋转卡壳用的调试信息
for (i=0;i<chnum;i++) fprintf(stderr,"%.2f %.2f\n",p[res[i]].x,p[res[i]].y);
for (i=0;i<appnum;i++)
{
fprintf(stderr,"APP : (%.2f %.2f)",p[app[i][0]].x,p[app[i][0]].y);
fprintf(stderr,"-- (%.2f %.2f)",p[app[i][1]].x,p[app[i][1]].y);
fprintf(stderr," \t dist=%.2f\n",dis(p[app[i][0]],p[app[i][1]]));
}
*/
/*暴力写法
ans=0;
for (i=0;i<chnum-1;i++)
for (j=i+1;j<chnum;j++)
ans=max(ans,dis(p[res[i]],p[res[j]]));
printf("%.f\n",ans*ans);
*/
}
}
return 0;
}
Followed by: Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator