見出し画像

Atcoder 典型90問032 - AtCoder Ekiden(★3)[順列全探索][配列で隣接を評価]

■要約

 正直★3の中では今まで解いてきた問題で一番複雑だった.解き方はすぐに思いついた.Nがとても小さいので,①各区間の走り方の全パターンを考えて,②それぞれに対して噂話を評価して,区間にかかる時間を更新していけばよいと考えた.①については,pythonでは

num = list(range(N))
ptn = list(itertools.permutations(num)) 

のようにすれば,順列の各パターンを配列として作ってくれるので簡単である.(bit全探索のときとおなじ要領).それに対し②に手こずった.答えを見たところ二次元配列を用意して,人xと人yがだめなペアだったら

grid[x][y]=False のようにすれば良いことを知った.こういうのを思いつくようになりたい.

from sys import stdin
import itertools

N = int(input())
A = [list(map(int, stdin.readline().split())) for l in range(N)]
M = int(input())
temp = [list(map(int, stdin.readline().split())) for l in range(M)]
ans = 10**18

grid = [[True]*N for _ in range(N)]
#中が悪い組だけFalseにする
for i in range(M):
 grid[temp[i][0]-1][temp[i][1]-1] = False
 grid[temp[i][1]-1][temp[i][0]-1] = False

#走る順番のパターンを作成
num = list(range(N))
ptn = list(itertools.permutations(num)) 


#各パターンごとに条件を満たし,マラソンにかかる時間をもとめる
for p in ptn:
 cnt = 0
 Bool = True
 #for文の範囲がずれるからわざわざBoolで判定する
 for j in range(N-1): 
   if grid[p[j]][p[j+1]] == False:
     Bool = False
     break
 if Bool:
   for j in range(N):
     cnt += A[p[j]][j] #A[人][何区]
   ans = min(ans, cnt)
 #print("cnt", cnt)
 #ans = min(ans, cnt)
if ans == 10**18:
 print(-1)
else:
 print(ans)
     

いいなと思ったら応援しよう!