바운드 배낭 문제를 0/1 배낭 문제로 변환


12

목표는 다른 프로그래밍 대신 동적 프로그래밍을 사용하는 것이 문제였습니다. 스팬 거리와 길이가 다른 케이블 세트가 있습니다. 거리에 정확히 도달하는 데 필요한 최소 케이블 수는 얼마입니까?

나에게 이것은 배낭 문제 처럼 보였지만 특정 길이의 배수가있을 수 있기 때문에 0/1 배낭 문제가 아닌 경계 배낭 문제였습니다. (각 항목의 값을 무게로 취급하십시오.) 검색된 공간의 확장에 신경 쓰지 않는 순진한 접근 방식을 취하면서, 제한된 배낭 문제를 0/1 배낭 문제로 변환하는 데 사용한 방법은 간단했습니다. 배수를 단일로 나누고 잘 알려진 동적 프로그래밍 알고리즘을 적용하십시오. 불행히도 이로 인해 차선책의 결과가 나옵니다.

예를 들어, 주어진 케이블 :
1 x 10ft,
1 x 7ft,
1 x 6ft,
5 x 3ft,
6 x 2ft,
7 x 1ft

목표 스팬이 13ft 인 경우 DP 알고리즘은 거리를 스팬하기 위해 7 + 6을 선택합니다. 욕심 많은 알고리즘은 10 + 3을 선택했을 것입니다. 그러나 최소한의 케이블 수를위한 넥타이입니다. 15 피트에 걸쳐있을 때 문제가 발생합니다. DP 알고리즘은 6 + 3 + 3 + 3을 선택하여 4 개의 케이블을 얻었고 욕심 많은 알고리즘은 3 개의 케이블에 대해서만 10 + 3 + 2를 올바르게 선택했습니다.

어쨌든, 0/1로 제한된 변환을 약간 스캔하면 여러 항목을 {p, 2p, 4p ...}로 변환하는 잘 알려진 접근법처럼 보입니다. 내 질문은 p + 2p + 4p가 여러 항목 수에 합산되지 않으면이 변환이 어떻게 작동합니까? 예를 들어 : 5 개의 3 피트 케이블이 있습니다. 3 + 2x3 + 4x3> 5x3이므로 {3, 2x3, 4x3}을 추가 할 수 없습니다. 대신 {3, 4x3}을 추가해야합니까?

[저는 현재 "오레곤 트레일 배낭 문제 (Oregon Trail Knapsack Problem)"문서를 작성하려고하지만 현재 동적 프로그래밍이 사용되지 않은 것처럼 보입니다.]


1
나는 이것이 math.stackexchange.com 또는 심지어 mathoverflow.net에
Oded

3
나는 일반적인 스택 오버 플로우와 여기에서 찢어졌습니다. 두 사이트 모두에서 FAQ를 읽으면이 사이트는 데이터 구조와 알고리즘을 먼저 나열합니다. 수학 사이트에 대한 FAQ를 읽으면 대신 cstheory 사이트에 묻는 것이 좋습니다.
개미

답변:


1

코드에 실수가있을 수 있습니다. Naryshkin이 언급 한 DP 프로그램을 작성했습니다. 대상 범위 13의 경우 6 + 7을보고하고 15의 경우 2 + 6 + 7을보고합니다.

# weight: cable length
# total weight: target span
# value: 1 for each cable
# want minimum number of cables, i.e. minimum total value

def knapsack_01_exact_min(weights, values, W):
    # 0-1 knapsack, exact total weight W, minimizing total value
    n = len(weights)
    values = [0] + values
    weights = [0] + weights
    K = [[0 for i in range(W+1)] for j in range(n+1)]
    choice = [[0 for i in range(W+1)] for j in range(n+1)]
    for i in range(1, n+1):
        for w in range(1, W+1):
            K[i][w] = K[i-1][w]
            choice[i][w] = '|'
            if w >= weights[i]:
                t = K[i-1][w-weights[i]]
                if (w==weights[i] or t) and (K[i][w]==0 or t+values[i] < K[i][w]):
                    choice[i][w] = '\\'
                    K[i][w] = t+values[i]
    return K[n][W], choice

def print_choice(choice, weights):
    i = len(choice)-1
    j = len(choice[0])-1
    weights = [0] + weights
    while i > 0 and j > 0:
        if choice[i][j]=='\\':
            print weights[i],
            j -= weights[i]
        i -= 1
    print

lens = [10, 7, 6] + 5*[3] + 6*[2] + 7*[1]
values = (3+5+6+7)*[1]
span = 13
v, choice = knapsack_01_exact_min(lens, values, span)
print "need %d cables to span %d:" % (v,span),
print_choice(choice, lens)

span = 15
v, choice = knapsack_01_exact_min(lens, values, span)
print "need %d cables to span %d:" % (v,span),
print_choice(choice, lens)

입력 길이의 순서를 조정하면 다른 최적의 솔루션을 제공 할 수 있습니다. 예를 들어 lens = 5*[3] + 6*[2] + 7*[1] + [10, 7, 6]15 = 10 + 2 + 3이됩니다.


'if (w-weights [i] == 0 또는 t) 및 (K [i] [w] == 0 또는 t + value [i] <K [i] [w] ) : '? DP 알고리즘의 소스를 잊어 버렸지 만 제로 검사가없는 경우 '(t + value [i] <K [i] [w])'만 확인하십시오.
Ants

1
당신은 정확한 총 무게를 풀고 있습니다. 즉, 아이템을 고를 때마다 (현재 단계의) 정확한 무게를 충족시켜야합니다. 따라서 아이템을 고르기로 결정할 때 두 번째 조항 인 "t + values ​​[i] <K [i] [w]"는 더 작은 총 가치를 갖도록합니다. 그러나 그 전에, 우리는 또한 필요한 무게를 가득 채울 필요가 있습니다. 즉, 첫 번째 i-1 품목은 무게를 가득 채울 수 있어야합니다 (w-weights [i]). -weights [i]] "(저는 임시 변수 t를 사용하고 있습니다).
jsz

"w == weights [i]"및 "K [i] [w] == 0"의 두 가지 추가 검사가 있습니다. 그것들은 필요하며 테이블이 초기화되는 방식으로 인해; 나는 당신이 그것을 만들 수있을 것이라고 생각하므로 세부 사항에 들어 가지 않을 것입니다. (w-weights [i] == 0을 w == weights [i]로 변경했습니다. 더 명확해야합니다).
jsz

1

바운드 배낭 문제를 0/1로 변환하는 데 사용한 방법은 여러 개의 동일한 항목을 갖는 것입니다. 다음과 같은 품목이 있다고 가정하십시오 (무게, 유틸리티로 제공됨).

  • 2 x 1, 2
  • 3 x 2, 3

다음 항목을 사용하여 0/1 문제로 변환합니다.

  • 1, 2
  • 1, 2
  • 2, 3
  • 2, 3
  • 2, 3

그리고 0/1 알고리즘을 사용하여 해결하십시오. 동일한 정확성의 솔루션이 여러 개있을 수 있으므로 임의의 솔루션을 선택하십시오.


이제 와이어 문제에 대해 : 케이블의 길이는 와이트이고 각 케이블의 값은 정확히 동일합니다 (양수 값은 작동하지만 1이라고 부릅니다). 이제 가장 선호하는 배낭 해결 알고리즘을 사용하지만 일반적으로 가치를 최대화하는 (부분) 솔루션을 선택하려면 최소화하는 솔루션을 선택하십시오. 또한 용량과 동일한 총 중량을 갖지 않는 모든 솔루션은 무시하십시오. 누군가가 원한다면 실제 코드로보다 구체적인 알고리즘을 작성할 수 있습니다.


그렇습니다. 그것이 바로 무게와 가치를 채우는 일입니다. 나는 분이 아닌 최대 가치를 계산했습니다. 방금 제안한대로 min을 계산하도록 코드를 변경하고 DP 테이블의 행 0을 MAXINT로 초기화했습니다. 여전히 동일한 결과, 배낭 문제에 대한 동적 프로그래밍 솔루션은 여전히 ​​10 + 3 + 2 또는 7 + 6 + 2 대신 6 + 3 + 3 + 3을 선택합니다.
개미
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.