WC 2010 efield 能量場

首先吐槽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;
      else
	return -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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章