Python 3, оценка = 1,57
Сначала наша змея перемещается по изображению, создавая вертикальные линии на равном расстоянии друг от друга.
Мы можем расширить эту змею, взяв две точки рядом друг с другом на вертикальной линии и создав петлю, конечными точками которой являются они.
| |
| => +----+
| +----+
| |
Мы организуем точки в пары, и для каждой пары мы сохраняем размер и среднее значение яркости петли, которая дает наибольшую среднюю яркость.
На каждом шаге мы выбираем пару с наибольшим значением, расширяем ее цикл, чтобы достичь максимальной средней яркости на расширении, и вычисляем новый оптимальный размер цикла и значение яркости для пары.
Мы храним триплеты (value, size, point_pair) в структуре кучи, отсортированной по значению, чтобы мы могли удалить самый большой элемент (в O (1)) и эффективно добавить новый модифицированный (в O (log n)).
Мы останавливаемся, когда достигаем предела количества пикселей, и эта змея будет последней змеей.
Расстояние между вертикальными линиями мало влияет на результаты, поэтому был выбран постоянный пиксель в 40 пикселей.
Полученные результаты
swirl 1.33084397946
chaos 1.76585674741
fractal 1.49085737611
bridge 1.42603926741
balls 1.92235115238
scream 1.48603818637
----------------------
average 1.57033111819
Примечание: оригинальная картинка «Крик» была недоступна, поэтому я использовал другую картинку «Крик» с аналогичным разрешением.
Gif, показывающий процесс расширения змеи на изображении «вихря»:
Код берет одно (или более разделенное пробелами) имя файла (ов) из стандартного ввода и записывает полученные изображения змей в файлы png и печатает результаты в стандартный вывод.
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)
.