Javascript ES6,738个字节
((V,C,L,r,k,n,A,G,F,e,i,j,q)=>p=>{p=p.map((p,i)=>({i:i,x:p[0],y:p[1]}));A=(f,p,a,b,v,i)=>{for(i=p[n],v=V(a,b);i--;)if(f(v,V(a,p[i])))return 1};G=(p,i,a)=>{for(i=p[n]-1,a=C(p[i],p[0]);i--;)a+=C(p[i],p[i+1]);if((a/=2)>r)r=a};F=(p,s,l,f,a,b,v)=>(l=s[n],f=s[0],a=s[l-2],b=s[l-1],e[a.i][b.i]||A((a,b)=>C(a,b)?0:a.x<0==b.x<0&&a.y<0==b.y<0&&L(a)>L(b),p,a,b)?0:(p=(v=V(a,b),p[k](x=>C(v,V(a,x))>=0)),A((a,b)=>C(a,b)>0,p,b,f)?0:(p.map(q=>F(p[k](r=>q!==r),[...s,q])),s[2]&&!p[n]&&!e[b.i][f.i]?G(s):0)));e=p.map(x=>p.map(y=>x===y));for(i=p[n];i--;){for(j=i;j--;){q=p[k]((p,x)=>x-i&&x-j);F(q,[p[i],p[j]]);F(q,[p[j],p[i]]);e[i][j]=e[j][i]=1}}console.log(r)})((a,b)=>({x:b.x-a.x,y:b.y-a.y}),(a,b)=>a.x*b.y-a.y*b.x,v=>v.x*v.x+v.y*v.y,0,'filter','length')
这是ES5或更低版本,可以在大多数浏览器和节点中正常运行,而无需进行调整:827字节
eval("(%V,C,L,r,k,n,A,G,F,e,i,j,q){@%p){p=p.map(%p,i){@{i:i,x:p[0],y:p[1]}});A=%f,p,a,b,v,i){for(i=p[n],v=V(a,b);i--;)if(f(v,V(a,p[i])))@1};G=%p,i,a){for(i=p[n]-1,a=C(p[i],p[0]);i--;)a+=C(p[i],p[i+1]);if((a/=2)>r)r=a};F=%p,s,l,f,a,b,v){@(l=s[n],f=s[0],a=s[l-2],b=s[l-1],e[a.i][b.i]||A(%a,b){@C(a,b)!=0?0:a.x<0==b.x<0&&a.y<0==b.y<0&&L(a)>L(b)},p,a,b)?0:(p=(v=V(a,b),p[k](%x){@C(v,V(a,x))>=0})),A(%a,b){@C(a,b)>0},p,b,f)?0:(p.forEach(%q){@F(p[k](%r){@q!==r}),s.concat([q]))}),s[2]&&p[n]==0&&!e[b.i][f.i]?G(s):0)))};e=p.map(%x,i){@p.map(%y,j){@i==j})});for(i=p[n];i--;){for(j=i;j--;){q=p[k](%p,x){@x!=i&&x!=j});F(q,[p[i],p[j]]);F(q,[p[j],p[i]]);e[i][j]=e[j][i]=1}}console.log(r)}})(%a,b){@{x:b.x-a.x,y:b.y-a.y}},%a,b){@a.x*b.y-a.y*b.x},%v){@v.x*v.x+v.y*v.y},0,'filter','length')".replace(/%/g,'function(').replace(/@/g,'return '))
代码返回一个匿名函数。作为参数,它需要一个点数组,例如[[0,1],[2,3],[4,5]]
。要使用它,您可以放在var f=
它前面,或者如果您想从命令行使用它,请添加(process.argv[2].replace(/ /g,'').slice(1,-1).split(')(').map((x)=>x.split(',')))
到最后,然后像这样调用它node convpol.js '(1,2)(3,4)(5,6)'
感谢您的挑战!由于没有参考实现,因此我无法证明这是正确的,但是至少对于点列表的排列而言,它是一致的。我几乎认为这没有用,因为带有调试代码的版本(甚至被禁用)随着指数时间的增加太慢了。我还是决定打高尔夫球,很高兴看到它在我的机器上下降到2秒以内得到50分。它可以在1分钟内计算大约130点。
该算法类似于Graham扫描,不同之处在于它必须在各处搜索空的凸包。
说明
这是该算法工作原理的高级概述。该算法的主要目的是搜索不包围点的逆时针凸环。该过程是这样的:
- 从一对点以及所有其他点的列表开始。
- 如果当前一对点正好穿过列表中的任何点,请停止。
- 顺时针过滤掉所有点对,因为它们会使多边形凹陷。
- 对于剩下的所有点,请执行以下操作:
- 如果从此点到链的第一个点的直线逆时针穿过或将任何点包围,请跳过此点,因为任何多边形都会将其包围。
- 将此点添加到链中,从步骤1开始,使用当前链和点列表进行递归。
- 如果没有剩余点,并且链中至少有3个点,则这是有效的凸多边形。记住这些多边形的最大面积。
另外,作为优化,我们记录了选中的链的初始对,因此在链中任何地方看到该对后,随后的任何搜索都可以立即停止搜索,因为已经找到了该对的最大多边形。
该算法永远不会找到一个多边形两次,而我已经实验验证了这一点。