본문 바로가기
Algorithm/코딩테스트 (Python)

[SWEA 4881][파이썬 S/W 문제해결 기본]. 5일차 - 배열 최소 합

by 싱브이 2023. 11. 3.
728x90
반응형

문제

NxN 배열에 숫자가 들어있다. 한 줄에서 하나씩 N개의 숫자를 골라 합이 최소가 되도록 하려고 한다. 단, 세로로 같은 줄에서 두 개 이상의 숫자를 고를 수 없다.

조건에 맞게 숫자를 골랐을 때의 최소 합을 출력하는 프로그램을 만드시오.

 

 

 

 

내 생각

백트래킹문제이다. 완전탐색을 이용하면 시간초과에 걸릴 수도 !! 즉, Purning(가지치기)를 잘해야한다!!!!!!

이번 문제는 시간도 꽤 걸리고, Pass하기까지 고난과 역경이 있었다,,

N과 N줄의 matrix 입력받기, 방문했는지 체크하기

min_num 최솟값을 global로 선언

가지치기에서는 최솟값이 total보다 작을 때 함수 끝내기 (return)

그리고 백트래킹을 이용하여 index가 배열길이 만큼 되었을 때 최솟값 비교!

처음에는 index가 N길이가 됐고, min_num이 total보다 크면 min_num=total그리고 함수를 끝냈다. 근데 10개 중에 6개만 Pass,,, 

이것도 맞긴 맞다 ! 근데 아마도 내 생각으로는 효율성에서 Fail이 뜨지 않았을까,, 생각해본다..

첫번째 코드의

if index == N:
    if min_num > total:
        min_num = total
        return

이 부분은 재귀 호출이 종료될 때마다 min_num을 검사하고 업데이트한다. 즉 모든 재귀 호출에서 검사하고 업데이트하기 때문에 불필요한 재귀호출이 있지 않았을까! 생각한다.

두번째 코드의

if min_num < total:
    return
if index == N:
    if min_num > total:
        min_num = total

이 부분은 조기 종료 조건을 분리해서 재귀 호출을 줄인 방법이다. min_num이 현재까지의 total보다 작은 경우 탐색하지 않고 return한다. 악 쉬운 문제이나 쉽지 않은 문제였다. 더 열심히 할 필요가 있다 !

 

 

 

 

내 코드

1. Fail 코드 (6/10) - 제한시간 초과

def backtrack(index, total):
    global min_num
    if index == N:
        if min_num > total:
            min_num = total
            return
    for i in range(N):
        if not visited[i]:
            visited[i] = True
            backtrack(index+1, total + matrix[index][i])  
            visited[i] = False

T = int(input())
for test_case in range(1, T + 1):
    N = int(input())
    matrix = [list(map(int, input().split())) for _ in range(N)]
    visited = [False] * N
    min_num = 1000
    backtrack(0, 0)
    print(f"#{test_case} {min_num}")

 

2. Pass

def backtrack(index, total):
    global min_num
    if min_num < total:
    	return
    if index == N:
    	if min_num > total:
    		min_num = total
    for i in range(N):
        if not visited[i]:
            visited[i] = True
            backtrack(index+1, total + matrix[index][i])  
            visited[i] = False

T = int(input())
for test_case in range(1, T + 1):
    N = int(input())
    matrix = [list(map(int, input().split())) for _ in range(N)]
    visited = [False] * N
    min_num = 1000
    backtrack(0, 0)
    print(f"#{test_case} {min_num}")
728x90
반응형

댓글