티스토리 뷰

알고리즘/백준

외판원 순회2 10971번 백준 파이썬

글을 쓰는 개발자 2020. 12. 7. 20:12
반응형

문제:www.acmicpc.net/problem/10971

 

10971번: 외판원 순회 2

첫째 줄에 도시의 수 N이 주어진다. (2 ≤ N ≤ 10) 다음 N개의 줄에는 비용 행렬이 주어진다. 각 행렬의 성분은 1,000,000 이하의 양의 정수이며, 갈 수 없는 경우는 0이 주어진다. W[i][j]는 도시 i에서 j

www.acmicpc.net

 

 
import sys
N = int(sys.stdin.readline().rstrip())
li=[]
for _ in range(N):
    li.append(list(map(int,sys.stdin.readline().rstrip().split())))
travel=[False]*N
final=0
ret=10000000000
def func(y,x,final,ans,cnt):
    global ret
    ans+=li[y][x]
    for i in range(N):
        if not travel[i] and li[x][i]!=0:
            travel[i]=True
            func(x,i,final,ans,cnt+1)
            travel[i]=False
    if cnt==N:
        if li[x][final]!=0:
            ans+=li[x][final]
            ret=min(ret,ans)
            return
        else:
            return



for i in range(N):
    for j in range(N):
        if i!=j and li[i][j]!=0:
            travel[i]=True
            travel[j]=True
            final=i
            func(i,j,final,0,2)
            travel[i]=False
            travel[j]=False
print(ret)

위의 코드는 내 풀이다. 풀이방법은 모든 점을 방문하는 것인데 이 때 cnt가 탈출 조건이다. cnt==N이고 마지막 도착점이 0이 아니라면 결과값을 비교하고 그렇지 않다면 그냥 return하는 식이다. 방문 여부는 travel로 bool값을 통해 확인한다. (위의코드는 pypy3로는 통과했지만 python3로는 시간초과가 나왔다.)

 

 

 

 

 
N=int(input())
W=[list(map(int,input().split()))for i in range(N)]
V=[0]*N
M=1e10
def back_track(n,c):
    global N,W,V,M
    if c<M:
        if all(V) and n==0:
            M=min(M,c)
        for i in range(N):
            if W[n][i]>0 and not V[i]:
                V[i]+=1
                back_track(i,c+W[n][i])
                V[i]-=1
back_track(0,0)
print(M)

위의 코드는 맞은사람 python3에서 상위에 있는 코드이다. 

함수 back_track(n,c)에서 n은 다음 위치를,c는 비용에 관한 것이다. 처음 if문은 이제 쓸데없는 연산을 멈추기 위한 수단이다. 만약 처음에 c가 39가 나와서 M이 39로 초기화 되었는데 다음 연산에서 42가 나오면 다음 것은 볼 것도 없으므로 넘기는 것이다. 다음 if문은 all(V)는 모든 위치를 방문 했느냐를 묻는 것이고 최종 목적지가 0이므로 n==0 인 경우에만 M값을 갱신 시켜준다.

 

all(x)는 반복 가능한(iterable) 자료형 x를 입력 인수로 받으며 이 x의 요소가 모두 참이면 True, 거짓이 하나라도 있으면 False를 돌려준다.

 

for문에는 모든 점들을 방문하는데 0값이 아니고 아직 방문 하지 않은 점들만 방문을 한다.

 

위의 코드를 보고나서 내 코드를 수정한 결과 python3로 시간초과가 안나고 통과하였다.

 

 

 
import sys
N = int(sys.stdin.readline().rstrip())
li=[]
for _ in range(N):
    li.append(list(map(int,sys.stdin.readline().rstrip().split())))
travel=[False]*N
final=0
ret=10000000000
def func(y,x,final,ans,cnt):
    global ret
    if ans<ret:
        ans+=li[y][x]
        for i in range(N):
            if not travel[i] and li[x][i]!=0:
                travel[i]=True
                func(x,i,final,ans,cnt+1)
                travel[i]=False
        if cnt==N:
            if li[x][final]!=0:
                ans+=li[x][final]
                ret=min(ret,ans)
                return
            else:
                return
    else:
        return



for i in range(N):
    for j in range(N):
        if i!=j and li[i][j]!=0:
            travel[i]=True
            travel[j]=True
            final=i
            func(i,j,final,0,2)
            travel[i]=False
            travel[j]=False
print(ret)

기존 코드에서 if ans<ret: else: return 이 두 줄만 추가하였다. 미리 계산하지 않을 것을 넘기니 시간초과 문제를 해결하였다.

반응형

'알고리즘 > 백준' 카테고리의 다른 글

링크와 스타트 15661번 백준  (0) 2020.12.08
맞춰봐 1248번 백준 파이썬  (0) 2020.12.08
10972번 다음 순열 백준  (0) 2020.12.06
15664번 N과M(10) 백준  (0) 2020.12.06
15663번 N과M(9) 백준  (0) 2020.12.06
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함