結果
問題 | No.5007 Steiner Space Travel |
ユーザー | Edomonndo365 |
提出日時 | 2023-04-26 16:48:01 |
言語 | PyPy3 (7.3.15) |
結果 |
AC
|
実行時間 | 947 ms / 1,000 ms |
コード長 | 4,907 bytes |
コンパイル時間 | 836 ms |
コンパイル使用メモリ | 87,252 KB |
実行使用メモリ | 83,776 KB |
スコア | 8,001,816 |
最終ジャッジ日時 | 2023-04-26 16:48:36 |
合計ジャッジ時間 | 31,346 ms |
ジャッジサーバーID (参考情報) |
judge12 / judge13 |
純コード判定しない問題か言語 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 937 ms
82,388 KB |
testcase_01 | AC | 939 ms
82,000 KB |
testcase_02 | AC | 940 ms
81,504 KB |
testcase_03 | AC | 942 ms
83,148 KB |
testcase_04 | AC | 938 ms
81,660 KB |
testcase_05 | AC | 946 ms
81,796 KB |
testcase_06 | AC | 938 ms
81,388 KB |
testcase_07 | AC | 939 ms
82,360 KB |
testcase_08 | AC | 942 ms
82,048 KB |
testcase_09 | AC | 937 ms
83,776 KB |
testcase_10 | AC | 944 ms
81,444 KB |
testcase_11 | AC | 941 ms
81,648 KB |
testcase_12 | AC | 937 ms
81,512 KB |
testcase_13 | AC | 940 ms
81,760 KB |
testcase_14 | AC | 947 ms
81,536 KB |
testcase_15 | AC | 937 ms
82,084 KB |
testcase_16 | AC | 942 ms
82,072 KB |
testcase_17 | AC | 939 ms
81,484 KB |
testcase_18 | AC | 940 ms
82,300 KB |
testcase_19 | AC | 944 ms
81,328 KB |
testcase_20 | AC | 940 ms
81,776 KB |
testcase_21 | AC | 941 ms
82,188 KB |
testcase_22 | AC | 944 ms
81,520 KB |
testcase_23 | AC | 946 ms
81,472 KB |
testcase_24 | AC | 938 ms
81,384 KB |
testcase_25 | AC | 939 ms
82,512 KB |
testcase_26 | AC | 936 ms
82,360 KB |
testcase_27 | AC | 938 ms
81,512 KB |
testcase_28 | AC | 942 ms
81,784 KB |
testcase_29 | AC | 943 ms
82,476 KB |
ソースコード
import sys from time import time from random import random, randrange, choice, choices from heapq import heappop, heappush from math import exp START = time() INF=10**9 def get_time(START): return time() - START def dist(p1,p2): x1,y1=p1 x2,y2=p2 return (x1-x2)**2 + (y1-y2)**2 def calc(i: int, j: int): d = dist(Terminals[ans[i]], Terminals[ans[j]]) if ans[i]<N: d*=5 if ans[j]<N: d*=5 return d def dijkstra(s: int, g: int): _dist = [INF] *(N+M) prev = [-1]*(N+M) que = [(0,s)] _dist[s]=0 while que: d, v = heappop(que) if _dist[v] < d: continue for nv in range(len(Terminals)): nd = dist(Terminals[v],Terminals[nv]) if v<N: nd*=5 if nv<N: nd*=5 nd += d if nd < _dist[nv]: prev[nv] = v _dist[nv] = nd heappush(que,(nd,nv)) res=[] v = g while v!=s: res.append(v) v = prev[v] return res[::-1] def kmeansplus(k,X_): #======= #k: クラスタ数 #X_ : データ点の座標を格納した配列 #======= X = X_[:] clusters = [] #初期重心を管理するリスト #1. データから一点を選択 centroid_id = choice([i for i in range(len(X))]) clusters.append(X[centroid_id]) X.pop(centroid_id) #選択した点を入力データのリストから除外 # 4. k 個のクラスタ中心を得られるまで計算を繰り返す。 while len(clusters) < k: dists = [] #2. 各データ点 と各クラスタ中心との距離を計算し、最も近いものを取り出す for i in range(len(X)): d = INF for j in range(len(clusters)): d = min(d, dist(X[i], clusters[j]) ) #今まで見た最短距離と今見てる距離との小さい方を選択 dists.append(d) len_dist = len(dists) #3. 確率分布にしたがって、データ点を1点選択してクラスタ中心とする。 new_c = choices([i for i in range(len_dist)], weights=dists, k=1)[0] #確率分布から点を一点取り出す clusters.append(X[new_c]) X.pop(new_c) #取り出した要素を消去 return clusters def calc_score(ans): score = 0 for i in range(len(ans)-1): score += calc(i,i+1) return score def probability(diff): start_temp=50 end_temp=10 temp = start_temp + (end_temp - start_temp) * get_time(START) / 0.85 return exp(diff/temp) # インプット N,M=map(int,input().split()) Terminals = [list(map(int,input().split())) for _ in range(N)] Stations = kmeansplus(M,Terminals) # k-means++法で配置 Terminals += Stations # dijkstraで初期解をgreedyに構築 v=0 ans = [v] visited = [False]*N visited[v]=True for _ in range(N-1): best_v = -1 best_dist = INF for nv in range(N): if visited[nv]: continue d = dist(Terminals[v], Terminals[nv]) if d < best_dist: best_dist = d best_v= nv assert best_v!=-1 path = dijkstra(v, best_v) ans += path v = best_v visited[v]=True ans += dijkstra(v,0) # 山登り n = len(ans) loop_cnt = 0 best_score = calc_score(ans) dx=(10,-10,0,0,5,5,-5,-5) dy=(0,0,10,-10,5,-5,5,-5) while get_time(START) < 0.85: loop_cnt+=1 p=random() if p<0.3: v1 = randrange(1,n-1) v2 = randrange(1,n-1) while v1==v2: v2 = randrange(1,n-1) ans[v1],ans[v2] = ans[v2],ans[v1] current_score = calc_score(ans) diff = best_score - current_score if diff>0: best_score = current_score #print("swap",current_score, file=sys.stderr) else: ans[v1],ans[v2] = ans[v2],ans[v1] else: v = randrange(N,N+M) original = Terminals[v][:] best_i = -1 sub_best_score = best_score for i in range(8): Terminals[v][0] = original[0]+dx[i] Terminals[v][1] = original[1]+dy[i] current_score = calc_score(ans) if current_score < sub_best_score: sub_best_score = current_score best_i = i if best_i != -1: best_score = sub_best_score Terminals[v][0] = original[0]+dx[best_i] Terminals[v][1] = original[1]+dy[best_i] #print("move",best_score, file=sys.stderr) else: Terminals[v]=original[:] # アウトプット for pos in Terminals[N:]: print(*pos) print(len(ans)) for v in ans: if v<N: print(1,v+1) else: print(2,v+1-N) print("Score", 10**9//(1000+calc_score(ans)**0.5), file=sys.stderr) print("Loop", loop_cnt, file=sys.stderr) print("time:",get_time(START) * 1000, file=sys.stderr)