Javascript ES6, 738 bayt
((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')
İşte çoğu tarayıcıda ve düğümde tweaking olmadan çalışması gereken bir ES5 veya daha az sürümü: 827 bytes
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 '))
Kod anonim bir işlev döndürür. Parametre olarak, bir dizi noktaya benzer [[0,1],[2,3],[4,5]]
. Kullanmak için var f=
önce yerleştirebilir veya komut satırından kullanmak isterseniz (process.argv[2].replace(/ /g,'').slice(1,-1).split(')(').map((x)=>x.split(',')))
sonuna ekleyin venode convpol.js '(1,2)(3,4)(5,6)'
Mücadele için teşekkürler! Referans uygulaması olmadığı için, bunun doğru olduğunu ispat edemem, ancak en azından puan listesinin izinleri için tutarlıdır. Neredeyse bunun işe yarayacağını düşünmemiştim, çünkü hata ayıklama koduna sahip sürümler, hatta devre dışı bırakılsa bile, üstel zaman artışı ile çok yavaşlardı. Yine de golf oynamaya karar verdim ve makinemde 50 puan için 2 saniyenin altına düştüğünü görmek beni mutlu etti. 1 dakikada yaklaşık 130 puan hesaplayabilir.
Algoritma Graham taramasına benzer , ancak her yerde boş dışbükey gövdeleri aramak zorunda olması dışında.
açıklama
İşte algoritmanın nasıl çalıştığına dair üst düzey bir bakış. Bu algoritmanın eti, sadece bir noktayı içermeyen saat yönünün tersine dışbükey döngüler arar. Prosedür böyle bir şeydir:
- Bir çift nokta ve diğer tüm noktaların bir listesiyle başlayın.
- Geçerli nokta çifti listedeki herhangi bir noktadan tamamen geçerse, durun.
- Poligonu içbükey yapacaklarından, tüm noktaları mevcut çiftin saat yönünde filtreleyin.
- Kalan tüm noktalar için aşağıdakileri yapın:
- Bu noktadan zincirin ilk noktasına kadar olan bir çizgi saatin tersi yönünde herhangi bir noktayı geçerse ya da çevrelerse, herhangi bir çokgen noktayı içine alacağından bu noktayı atlayın.
- Bu noktayı zincire ekleyin, 1. adımdan itibaren geçerli zincir ve noktaların listesiyle tekrarlayın.
- Hiçbir nokta kalmamışsa ve zincir en az 3 puana sahipse, bu geçerli bir dışbükey çokgendir. Bu çokgenlerin en geniş alanını hatırla.
Ayrıca, bir optimizasyon olarak, zincirin ilk çiftini kontrol edilmiş olarak kaydederiz, böylece bu çiftin zincirde herhangi bir yerinde görüldükten sonraki aramalar hemen aramayı durdurabilir, çünkü bu çiftin en büyük poligonu zaten bulundu.
Bu algoritma asla iki kez çokgen bulamamalı ve bunu deneysel olarak doğruladım.