結果

問題 No.5007 Steiner Space Travel
ユーザー titan23titan23
提出日時 2022-10-06 17:49:47
言語 PyPy3
(7.3.15)
結果
TLE  
実行時間 -
コード長 4,980 bytes
コンパイル時間 2,074 ms
実行使用メモリ 91,532 KB
スコア 6,060,542
最終ジャッジ日時 2022-10-06 17:50:23
合計ジャッジ時間 33,139 ms
ジャッジサーバーID
(参考情報)
judge14 / judge15
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 987 ms
89,180 KB
testcase_01 AC 993 ms
88,960 KB
testcase_02 AC 989 ms
88,320 KB
testcase_03 AC 986 ms
88,616 KB
testcase_04 AC 987 ms
88,856 KB
testcase_05 AC 989 ms
88,408 KB
testcase_06 AC 988 ms
89,868 KB
testcase_07 TLE -
testcase_08 AC 990 ms
90,680 KB
testcase_09 AC 988 ms
86,984 KB
testcase_10 AC 988 ms
90,708 KB
testcase_11 AC 988 ms
88,972 KB
testcase_12 AC 987 ms
87,552 KB
testcase_13 AC 987 ms
89,964 KB
testcase_14 AC 995 ms
87,988 KB
testcase_15 AC 988 ms
91,532 KB
testcase_16 AC 996 ms
88,556 KB
testcase_17 AC 995 ms
87,932 KB
testcase_18 AC 987 ms
89,496 KB
testcase_19 AC 990 ms
88,616 KB
testcase_20 AC 997 ms
88,860 KB
testcase_21 AC 990 ms
90,656 KB
testcase_22 AC 988 ms
91,004 KB
testcase_23 AC 987 ms
89,408 KB
testcase_24 AC 996 ms
91,348 KB
testcase_25 AC 988 ms
90,352 KB
testcase_26 AC 988 ms
89,636 KB
testcase_27 AC 988 ms
90,588 KB
testcase_28 AC 989 ms
90,408 KB
testcase_29 AC 990 ms
88,940 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

from itertools import permutations
import sys
import random
import time
import math
input = lambda: sys.stdin.readline().rstrip()
random.seed(0)

START_TIME = time.time()
N, M = map(int, input().split())
AB = [list(map(int, input().split())) for _ in range(N)]

def fit():
  labels_ = []
  now = 0
  while len(labels_) < N:
    labels_.append(now)
    now += 1
    if now == 8:
      now = 0
  random.shuffle(labels_)
  cluster_centers_ = [(0, 0) for _ in range(8)]
  for _ in range(10):
    syuukei = [[] for _ in range(8)]
    for i in range(N):
      syuukei[labels_[i]].append(AB[i])
    for i,l in enumerate(syuukei):
      if l:
        x, y = sum(x for x,y in l)//len(l), sum(y for x,y in l)//len(l)
      else:
        x, y = 1<<30, 1<<30
        x, y = random.randint(0, 1000), random.randint(0, 1000)
      cluster_centers_[i] = [x, y]
    for i in range(N):
      dist = 1<<30
      for j in range(8):
        tmp = (AB[i][0] - cluster_centers_[j][0])**2 + (AB[i][1] - cluster_centers_[j][1])**2
        if tmp < dist:
          dist = tmp
          labels_[i] = j
  return labels_, cluster_centers_

def dist(a, b):
  return (a[0] - b[0])**2 + (a[1] - b[1])**2

def make_ans():
  labels, centers = fit()

  ANS = []
  L = [[] for _ in range(8)]
  for i, cluster_number in enumerate(labels):
    L[cluster_number].append(i)

  vest_p = None
  vest = 1<<30
  for p in permutations(range(8)):
    score = dist((AB[0]), centers[p[0]])
    for i in range(len(centers)-1):
      score += dist(centers[p[i]], centers[p[i+1]])
    score += dist(centers[p[-1]], AB[0])
    if score < vest:
      vest = score
      vest_p = p[:]
  if time.time() - START_TIME > 0.9:
    return 1<<30, -1, -1
  ans = [(1, 0)]
  for i in vest_p:
    if i >= len(L): continue
    ans.append((2, i))
    for j in range(len(L[i])):
      d1 = 5 * dist(AB[L[i][j]], centers[i])
      d2 = 1<<30
      if j+1 < len(L[i]):
        d2 = 25* dist(AB[L[i][j]], AB[L[i][j+1]])
      if d2 < d1:
        ans.append((1, L[i][j]))
      else:
        ans.append((1, L[i][j]))
        ans.append((2, i))
  ans.append((1, 0))

  score = 0
  for i in range(len(ans)-1):
    type_pre, indx_pre = ans[i]
    type_now, indx_now = ans[i+1]
    if   type_pre == 1 and type_now == 1:
      score += 25*dist(AB[indx_pre], AB[indx_now])
    elif type_pre == 1 and type_now == 2:
      score +=  5*dist(AB[indx_pre], centers[indx_now])
    elif type_pre == 2 and type_now == 1:
      score +=  5*dist(centers[indx_pre], AB[indx_now])
    elif type_pre == 2 and type_now == 2:
      score +=    dist(centers[indx_pre], centers[indx_now])
  return round(10**9 / (1000 + score**.5)), ans, centers

def main():
  ANS = []
  CENTERS = []
  FINAL_VESTSCORE = 1<<30

  # ======================
  # 初期解生成
  cnt = 0
  while time.time() - START_TIME < 0.5:
    cnt += 1
    score, ans, centers = make_ans()
    if score < FINAL_VESTSCORE:
      FINAL_VESTSCORE = score
      ANS = ans[:]
      CENTERS = centers
      print(score, file=sys.stderr)
  print(cnt, file=sys.stderr)
  # ======================
  def debug(*args):
    print(*args, file=sys.stderr)
  # ======================
  # 焼きなまし
  
  def modify(centers):
    i = random.randint(0, 7)
    d1 = random.randint(-5, 5)
    d2 = random.randint(-5, 5)
    centers[i][0] += d1
    centers[i][1] += d2
    if centers[i][0] < 0:
      centers[i][0] = 0
    if centers[i][1] < 0:
      centers[i][1] = 0
    if centers[i][0] > 1000:
      centers[i][0] = 1000
    if centers[i][1] > 1000:
      centers[i][1] = 1000
    return centers

  def calc(new_centers):
    score = 0
    for i in range(len(ANS)-1):
      type_pre, indx_pre = ANS[i]
      type_now, indx_now = ANS[i+1]
      if   type_pre == 1 and type_now == 1:
        score += 25*dist(AB[indx_pre], AB[indx_now])
      elif type_pre == 1 and type_now == 2:
        score +=  5*dist(AB[indx_pre], new_centers[indx_now])
      elif type_pre == 2 and type_now == 1:
        score +=  5*dist(new_centers[indx_pre], AB[indx_now])
      elif type_pre == 2 and type_now == 2:
        score +=    dist(new_centers[indx_pre], new_centers[indx_now])
    return round(10**9 / (1000 + score**.5))

  START_TEMP, END_TEMP = 6000, 1000
  TIME_LIMIT = 0.9
  FINAL_CENTERS = CENTERS[:]
  vestscore = FINAL_VESTSCORE
  cnt = 0
  while time.time() - START_TIME < TIME_LIMIT:
    cnt += 1
    new_centers = modify(CENTERS[:])
    new_score = calc(new_centers)
    temp = START_TEMP + (END_TEMP - START_TEMP) * (time.time() - START_TIME) / TIME_LIMIT
    prob = math.exp((new_score - vestscore) / temp)
    if prob > random.random():
      vestscore = new_score
      CENTERS = [c[:] for c in new_centers]
      if new_score > FINAL_VESTSCORE:
        FINAL_VESTSCORE = new_score
        FINAL_CENTERS = [c[:] for c in new_centers]
  debug('cnt', cnt)
  # ======================

  for c, d in FINAL_CENTERS:
    print(c, d)
  print(len(ANS))
  for a, b in ANS:
    print(a, b+1)
  debug(FINAL_VESTSCORE)

main()
0