Python 3, wynik = 1,57
Najpierw nasz wąż podróżuje po obrazie, tworząc pionowe linie w równej odległości od siebie.
Możemy rozszerzyć tego węża, biorąc dwa punkty obok siebie w linii pionowej i tworząc pętlę, której punktami końcowymi są one.
| |
| => +----+
| +----+
| |
Organizujemy punkty w pary i dla każdej pary przechowujemy rozmiar i średnią wartość jasności pętli, która daje największą średnią jasność.
Na każdym kroku wybieramy parę z najwyższą wartością przedłużenia pętli, aby osiągnąć maksymalną średnią jasność na przedłużeniu i obliczamy nowy optymalny rozmiar pętli i wartość jasności dla pary.
Przechowujemy trojaczki (wartość, rozmiar, para_punkt) w strukturze sterty posortowanej według wartości, dzięki czemu możemy usunąć największy element (w O (1)) i wydajnie dodać nowy zmodyfikowany (w O (log n)).
Zatrzymujemy się, gdy osiągniemy limit liczby pikseli, a ten wąż będzie ostatnim wężem.
Odległość między pionowymi liniami ma bardzo niewielki wpływ na wyniki, dlatego wybrano stałą 40 pikseli.
Wyniki
swirl 1.33084397946
chaos 1.76585674741
fractal 1.49085737611
bridge 1.42603926741
balls 1.92235115238
scream 1.48603818637
----------------------
average 1.57033111819
Uwaga: oryginalne zdjęcie „Krzyk” nie było dostępne, więc użyłem innego obrazu „Krzyk” o podobnej rozdzielczości.
Gif przedstawiający proces rozciągania węża na obrazie „wirowania”:
Kod pobiera jedną (lub więcej oddzielonych spacjami) nazwę pliku ze standardowego wejścia i zapisuje powstałe obrazy węża do plików png i drukuje wyniki na standardowe wyjście.
from PIL import Image
import numpy as np
import heapq as hq
def upd_sp(p,st):
vs,c=0,0
mv,mp=-1,0
for i in range(st,gap):
if p[1]+i<h:
vs+=v[p[0],p[1]+i]+v[p[0]+1,p[1]+i]
c+=2
if vs/c>mv:
mv=vs/c
mp=i
return (-mv,mp)
mrl=[]
bf=input().split()
for bfe in bf:
mr,mg=0,0
for gap in range(40,90,1500):
im=Image.open(bfe)
im_d=np.asarray(im).astype(int)
v=im_d[:,:,0]+im_d[:,:,1]+im_d[:,:,2]
w,h=v.shape
fp=[]
sp=[]
x,y=0,0
d=1
go=True
while go:
if 0<=x+2*d<w:
fp+=[(x,y)]
fp+=[(x+d,y)]
sp+=[(x-(d<0),y)]
x+=2*d
continue
if y+gap<h:
for k in range(gap):
fp+=[(x,y+k)]
y+=gap
d=-d
continue
go=False
sh=[]
px=im.load()
pl=[]
for p in fp:
pl+=[v[p[0],p[1]]]
px[p[1],p[0]]=(0,127,0)
for p in sp:
mv,mp=upd_sp(p,1)
if mv<=0:
hq.heappush(sh,(mv,1,mp+1,p))
empty=False
pleft=h*w//3
pleft-=len(fp)
while pleft>gap*2 and not empty:
if len(sh)>0:
es,eb,ee,p=hq.heappop(sh)
else:
empty=True
pleft-=(ee-eb)*2
mv,mp=upd_sp(p,ee)
if mv<=0:
hq.heappush(sh,(mv,ee,mp+1,p))
for o in range(eb,ee):
pl+=[v[p[0],p[1]+o]]
pl+=[v[p[0]+1,p[1]+o]]
px[p[1]+o,p[0]]=(0,127,0)
px[p[1]+o,p[0]+1]=(0,127,0)
pl+=[0]*pleft
sb=sum(pl)/len(pl)
ob=np.sum(v)/(h*w)
im.save(bfe[:-4]+'snaked.png')
if sb/ob>mr:
mr=sb/ob
mg=gap
print(bfe,mr)
mrl+=[mr]
print(sum(mrl)/len(mrl))
[![image description](SE URL for downsized image)](URL for original image)
.