結果

問題 No.5007 Steiner Space Travel
ユーザー titan23titan23
提出日時 2022-10-06 20:45:12
言語 PyPy3
(7.3.15)
結果
AC  
実行時間 950 ms / 1,000 ms
コード長 5,328 bytes
コンパイル時間 375 ms
実行使用メモリ 87,728 KB
スコア 7,521,332
最終ジャッジ日時 2022-10-06 20:45:44
合計ジャッジ時間 31,925 ms
ジャッジサーバーID
(参考情報)
judge12 / judge16
純コード判定しない問題か言語
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 939 ms
86,616 KB
testcase_01 AC 940 ms
86,576 KB
testcase_02 AC 948 ms
87,324 KB
testcase_03 AC 946 ms
87,716 KB
testcase_04 AC 934 ms
87,352 KB
testcase_05 AC 935 ms
86,340 KB
testcase_06 AC 935 ms
86,860 KB
testcase_07 AC 945 ms
87,104 KB
testcase_08 AC 935 ms
86,336 KB
testcase_09 AC 935 ms
86,832 KB
testcase_10 AC 939 ms
87,224 KB
testcase_11 AC 945 ms
87,036 KB
testcase_12 AC 948 ms
86,968 KB
testcase_13 AC 939 ms
87,548 KB
testcase_14 AC 946 ms
87,028 KB
testcase_15 AC 942 ms
86,812 KB
testcase_16 AC 943 ms
87,728 KB
testcase_17 AC 933 ms
87,264 KB
testcase_18 AC 944 ms
86,376 KB
testcase_19 AC 941 ms
87,376 KB
testcase_20 AC 950 ms
87,240 KB
testcase_21 AC 937 ms
87,608 KB
testcase_22 AC 944 ms
87,724 KB
testcase_23 AC 937 ms
86,612 KB
testcase_24 AC 934 ms
86,776 KB
testcase_25 AC 937 ms
86,820 KB
testcase_26 AC 936 ms
86,588 KB
testcase_27 AC 949 ms
87,192 KB
testcase_28 AC 934 ms
86,716 KB
testcase_29 AC 936 ms
86,724 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_)
  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))

    vest_path = []
    vest_dist = 1 << 30
    for _ in range(10):
      tmp_path = []
      tmp_dist = 0
      random.shuffle(L[i])
      for j in range(len(L[i])):
        d1 = 2 * 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:
          tmp_path.append((1, L[i][j]))
          tmp_dist += d2
        else:
          tmp_path.append((1, L[i][j]))
          tmp_path.append((2, i))
          tmp_dist += d1 * 2
      if tmp_dist < vest_dist:
        vest_dist = tmp_dist
        vest_path = tmp_path[:]
    ans.extend(vest_path)
  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 = 0

  # ======================
  # 初期解生成
  cnt = 0
  while time.time() - START_TIME < 0.8:
    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 = 1000, 10
  TIME_LIMIT = 0.85
  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)


main()
0