WC 2010 efield 能量场

来源:互联网 发布:京东java在线笔试题 编辑:程序博客网 时间:2024/05/22 09:41

首先吐槽WC2010:完全毁了“WC不可做”的神奇形象。。。。。。

首先是本弱菜被误导了,以为是个动态规划。。。。。。

废话少说,首先mamb(ca-cb)化成maca*mb-mbcb*ma。。。这告诉我们关于两者相关的式子,要往把单体信息化到一起,可能会发现很神奇的东西。。。

令xa=maca ya=ma,上式就成了叉积。。。

所以原题就成了给定在第一象限的n个点,求两两最大叉积的方案,和最大简单多边型面积。。。之所以是简单多边形,因为要求负值要连续,又要最大,那么就是凸包了。。。

那么讲一下两两叉积最大吧。。。首先方案一定时凸包上两点。。。因为凸包上两点才可以达到点集最大距离。。。而叉积最大又是可以等价于方案两点与原点形成的平行四边形面积最大。。。一种方法:将原点“加入"凸包,固定原点为三角形上的一点卡壳法求最大三角形。。。

然后注意方案输出顺序。。。

Code:

#include<cstdio>#include<cstdlib>#include<cmath>#include<cstring>#define zero(x) ((fabs(x)<1e-8))struct point{  double x,y;} qup[50005],qdn[50005],que[50005],node[50005];int indexup[50005],indexdn[50005],index[50005],n=0,hea=0,tai=0,top=0,ansi=0,ansj=0,oriindex[50005];double ans2=0;int cmp(const void *p,const void *q){  int a=*(int*)p,b=*(int*)q;  if (zero(node[a].x-node[b].x))    if (zero(node[a].y-node[b].y))      return 0;    else      if (node[a].y-node[b].y>0)return 1;      elsereturn -1;  else    if (node[a].x-node[b].x>0)      return 1;    else      return -1;}double cross(point a,point b,point c,point d){  b.x-=a.x;b.y-=a.y;  d.x-=c.x;d.y-=c.y;  return b.x*d.y-d.x*b.y;}double cross(point a,point b){  return a.x*b.y-b.x*a.y;}int main(){  freopen("efield.in","r",stdin);  freopen("efield.out","w",stdout);  scanf("%d",&n);  int i=0,j=0;  for (i=1;i<=n;i++)    {      scanf("%lf%lf",&node[i].y,&node[i].x);      node[i].x=node[i].x*node[i].y;      oriindex[i]=i;    }  qsort(oriindex+1,n,sizeof(oriindex[0]),cmp);  qup[++hea]=node[oriindex[1]];  qup[++hea]=node[oriindex[2]];  qdn[++top]=node[oriindex[1]];  qdn[++top]=node[oriindex[2]];  indexup[1]=indexdn[1]=oriindex[1];  indexup[2]=indexdn[2]=oriindex[2];  for (i=3;i<=n;i++)    {      while (cross(qup[hea-1],qup[hea],qup[hea],node[oriindex[i]])>=0 && hea>1) hea--;      while (cross(qdn[top-1],qdn[top],qdn[top],node[oriindex[i]])<=0 && top>1) top--;      qup[++hea]=node[oriindex[i]];      indexup[hea]=oriindex[i];      qdn[++top]=node[oriindex[i]];      indexdn[top]=oriindex[i];    }  for (i=1;i<=hea;i++)    que[++tai]=qup[i],index[tai]=indexup[i];  for (i=top-1;i>1;i--)    que[++tai]=qdn[i],index[tai]=indexdn[i];  j=1;  for (i=1;i<=tai;i++)    {      while (fabs(cross(que[i],que[j==tai?1:j+1]))>fabs(cross(que[i],que[j]))) j=j==tai?1:j+1;      if (fabs(cross(que[i],que[j]))>ans2){  ansi=i;  ansj=j;  ans2=fabs(cross(que[i],que[j]));}    }  if (cross(que[ansi],que[ansj])>=0)    printf("%d %d\n",index[ansi],index[ansj]);  else    printf("%d %d\n",index[ansj],index[ansi]);  printf("%d\n",tai);  for (i=tai;i>=1;i--) printf("%d ",index[i]);  return 0;}


原创粉丝点击