• 카테고리

    질문 & 답변
  • 세부 분야

    알고리즘 · 자료구조

  • 해결 여부

    해결됨

5강 최적화 19942번 질문드립니다.

23.08.26 19:16 작성 23.08.26 19:16 수정 조회수 205

1

제가 코드를 짰는데 99퍼에서 오답처리가 났는데 어느부분을 놓쳤는지 모르겠어서 질문 드립니다.

코드 한 번 봐주실 수 있을까요..

def func(idx,p,f,s,v,sum1):
    global min_sum
    if sum1 > min_sum:
        return
    if idx == N:
        if p >= mp and f >= mf and s >= ms and v >= mv:
            if sum1 < min_sum:
                min_sum = sum1
                last1 = ''.join(map(str, visited))
                dict1[min_sum] = last1
                return
            elif sum1 == min_sum:
                return
        else:
            return
    else:
        visited[idx+1] = 1
        func(idx+1,p+info[idx][0],f+info[idx][1],s+info[idx][2],v+info[idx][3],sum1+info[idx][4])
        visited[idx+1] = 0
        func(idx+1,p,f,s,v,sum1)


N = int(input())
mp, mf, ms, mv = map(int, input().split())
info = [list(map(int, input().split())) for _ in range(N)]
min_sum = 999999999999999999
visited = [0] * (N+1)
dict1 = {}
func(0,0,0,0,0,0)

if min_sum == 999999999999999999:
    print(-1)
else:
    print(min_sum)
    for i in range(1,N+1):
        if dict1[min_sum][i] == '1':
            print(i, end=' ')

답변 2

·

답변을 작성해보세요.

1

박성인님의 프로필

박성인

질문자

2023.08.26

답변 감사합니다!!

아직 이해 안되는 부분이 있어 댓글 답니다!

제가 강의를 보면서 이해한건

idx == N 까지 확인하는 경우면 결국 첫번째부터 마지막 요소까지 o,x로 그려나가면서

모든 부분집합을 훑는다고 이해했는데 이 부분에서 탐색하지 못한 반례가 있을 수 있는건가요?

 image

아래 반례를 확인해보시면 됩니다!

 

제가 쓴 코드는, idx가 끝에 도달하지 않아도 정답 조건을 만족하면 정답을 업데이트 하고 종료되지만,

성인님이 쓴 코드는 반드시 마지막 idx에 도달하도록 조건이 걸려 있기 때문에,

영양소가 없는 재료 ( 좀 억지 반례이긴 하지만 ) 가 있다는 가정 하에 아래와 같이 다른 결과가 나오게 됩니다!

[반례]

3

0 0 0 1

0 0 0 1 1

0 0 0 0 0

0 0 0 0 0

 

[성인님이 쓴 코드 결과]

1

1 2 3

dict1 = {1: '0111'}

[제가 쓴 코드 결과]

1

1

dict1 = {1: '0100'}


이런 반례는 사실 저도, 처음부터 이런 반례가 있겠군! 하고 생각하고 푸는 건 아니고

조건문의 사용이나 가지치기의 위치, 등을 조금 반례가 생기지 않도록 문제를 계속 풀어보고 조정해 나가면서 자연스럽게 알게 되는 스킬이라서 정말로 좋은 질문이었습니다!

반례가 조금 억지네요.. 어이없다

 

박성인님의 프로필

박성인

질문자

2023.08.26

와..

아 이해했습니다

늦은시간에 답변 주셔서 감사합니다

1

조금 수정해봤습니다.

 

보내주신 코드와 결정적으로 다른점은

보내주신 코드

[ idx ==N일 때만, 영양소 조건을 확인해서 정답을 업데이트]

수정 한 코드

[ idx ==N이 아니더라도, 영양소 조건을 확인해서 정답을 업데이트]

 

해당 부분에 반례가 존재해서 99%에서 오류가 발생하는 것 같아요!

혹시라도 이해가 안되신다면 답글 남겨주세요!

 

def func(idx,p,f,s,v,sum1):
    global min_sum

    # 가지치기
    if sum1 > min_sum:
        return
    
    # 정답 업데이트    
    if p >= mp and f >= mf and s >= ms and v >= mv:
        if sum1 < min_sum:
            min_sum = sum1
            last1 = ''.join(map(str, visited))
            dict1[min_sum] = last1
            return
        
    # 인덱스 끝에 도달하면 탐색 종료    
    if idx == N:
        return
    
    # 탐색
    else:
        visited[idx+1] = 1
        func(idx+1,p+info[idx][0],f+info[idx][1],s+info[idx][2],v+info[idx][3],sum1+info[idx][4])
        visited[idx+1] = 0
        func(idx+1,p,f,s,v,sum1)


N = int(input())
mp, mf, ms, mv = map(int, input().split())
info = [list(map(int, input().split())) for _ in range(N)]
min_sum = 999999999999999999
visited = [0] * (N+1)
dict1 = {}
func(0,0,0,0,0,0)

if min_sum == 999999999999999999:
    print(-1)
else:
    print(min_sum)
    for i in range(1,N+1):
        if dict1[min_sum][i] == '1':
            print(i, end=' ')