--01 가동 파격적인베이스 배낭 문제 (배낭 문제 Ⅱ)

주제 출처 : 칼라 버클 | LintCode

I-A 및 상품 J 배낭의 총용량. 무게 주어진 배열의 각 항목의 가중치를 나타내고, 배열 값이 최대 값을 찾고, 각 항목의 값이다. (항목은 분리 될 수 없다)

배낭 문제 II

이 질문은 즉, 재귀 및 재귀 (반복)는, 전자가 더 나은 후자보다 이해 두 가지 방법으로 구현 된 동적 프로그래밍 (DP) 기본적인 질문 알고리즘이다.

문제 해결 아이디어

첫째, 주제는 우리가 어떻게 자신의 가게 그것의 최대 값을 만들기 위해 할 수 있도록, 최대 값을 찾을 필요합니까? 기사는 무게를 가지고 있기 때문에 우리는 항상 예를 들어, 가장 큰 항목의 값을 넣을 수 있도록 배낭의 용량이 배낭 (10)의 용량을 가정, 제한, 세 개의 중량 값 사이의 관계를 해당하는 항목으로 다음과 같은 테이블이 있습니다
품질 | | 가치 항목
10 8
B (6) 5
C 5 4
분명히 우리는, 모든 비용 효율적인 선택 (가치 / 품질) 라인 (욕심 알고리즘)에 가장 큰 아니지만, 거기에 B와 C를 선택한 다음 누군가가 플래시 할 수있는 주제 우리가 실제로 욕심 알고리즘을 사용할 수 있도록 요구 사항 "항목은 분할 할 수 없습니다."
우리는 사고의 가장 일반적인 방법에서 재귀 공식을 프로그래밍 동적를 얻을 수 있습니다. 우리는 i 번째 선형 물체를 통과 할 수 있도록 우리는 보통 사람의 아이디어에 따라 계정으로 상황의 무게를 고려하여 i 번째 항목이이 라인에 가장 큰 하나를 선택,이 조합의 값을 비교 한 다음 다양한 조합을 찾을 때 그는 두 가지 옵션과 "하지 마" "해야한다",있다
, 각 항목은 다음 두 가지 옵션을 경험 결국 모든 조합을 생성 할 것이다. 물품의 i 번째 턴은 우리의 최대 값은 이러한 수식 경우 : MAXVALUE = 최대 (값 [I ] 값 [I-1] () 및 척 수있는 각 선택 배낭을 고려) 상황의 i 번째 기사를 제품의 i 번째 값에 의미가 아닌 것은 I-1, 최대 값이 수식 항목 또는 전체 배낭에 전달되었을 것입니다, 그래서 때 알고 우리가 필요로하는 판사의 전 항목 이후 가장 컸다 이 순환 과정을 해결하기 위해 기대하지 수 있도록 모든 이상을 확인합니다.

재귀 알고리즘

우리는 각 프로그램 항목에 대한 정보를 알 필요가 각 항목에 대응하는 (도 사용될 수있다 구조체의 배열) 두 배열의 정보를 저장 할 필요가 있고, 각각의 값 [], 무게 []. 재귀 절차는 파라미터의 변화를 요구하고, 상품의 중량, 배낭 및 문서의 잔존 용량은, (배낭의 J의 i 번째 항목 전에 잔량을 함수 봉투를 작성하는 것이 가능하다는 것을 명확하게 될 때의 값이 변경되지 );

  1. 실측치 순환 배출구가
    , 상기 남은 여유 공간 또는 배낭 간주 완성품을 언급 즉 (j == 0 || I == 0 ), 최대 값이되는은 0을 반환한다 가리키고;
  2. 재귀 관계
    이 관계는 두 개의 비교적 쉽게 생각할 MAXVALUE = 최대 (백 (I- 갖는 1, J), 백 (I-1, J-중량 [I])의 값 + [I]하기) "전이며 "해야한다"후자는, "하지 말고
    또한 더 많은 공간의 나머지 부분보다 J = 0하지만 아이템의 무게가 현재 선택된 무게 [I] J,이 글, 즉 강제 선택을 건너 뜁니다하는 경우를! "하지 마."
    우리는 그것을 얻기 위해 두 예비 재귀 알고리즘을 완료 할 수있을 것입니다!
int bag(int i, int j)  //递归实现
{
    if (i == 0 || j == 0)
        return 0;
    if (weight[i] > j)
        return bag(i-1,j);
    else {
        int res = max(bag(i - 1, j), bag(i - 1, j - weight[i]) + value[i]);
        return res;
    }
        //max函数可以自己判断每一种情况下的最大价值(TIPS:对于递归程序不能刻意去思考它的过程,主要理解它的方向)
}

그러나 이것은 효율이 매우 가난하기 때문에, 우리는이 경우 수백, 필연적으로이 반복됩니다 계산 발견, DP 호출 할 수 없습니다, 항목의 반복 노드 I, J의 무게 될 수있다,의 기록을 만들 수 있습니다 그 효율이 크게 향상 될 수 있도록 2 차원 어레이의 MAXDATA [I] [J]를 위해 각 I, J는 경우,이 경우에 저장되어있는 최대 값이고

int bag(int i, int j)  //递归实现
{
    if (maxdata[i][j] != EOF)   //一开始让每个点都等于EOF(-1),如果不是-1证明这个情况已经算过了,可以直接return
        return maxdata[i][j];
    if (i == 0 || j == 0)
        return 0;
    if (weight[i] > j)
        return bag(i-1,j);
    else {
        int res = max(bag(i - 1, j), bag(i - 1, j - weight[i]) + value[i]);
        maxdata[i][j] = res;     //没算过就存一下
        return res;
    }
}

반복 알고리즘

반복 알고리즘은, 대조적으로, 처음부터 최대 값을 발견하고 점차적으로 i 번째 기사를 얻기 위해다면 반복 알고리즘과 재귀의 재귀 알고리즘 차별화 된 자연을 우리는 i 번째 나머지 하나에서 항목을 발견했다 최대 값, 우리는 기록해야 그 무게의 다양한 제품의 전 종류 전에 가장 큰 값. (더 어렵습니다 어떤 점을 이해하기)
하지만 구체적인 판단 방법은 아직 "해야한다"와 "하지"문제입니다. 이 개시로부터 때문에, 우리는 라운드 키 포인트는 재귀 그 중량 또는 그 재귀 맥스 (MAXDATA [J], 최대 등 [J 웨이트 [I] + 값 [I]) 하지만 이것은 이전 라운드에서 저장된 배열 데이터에 기초하여 결정된다.
그럼이 재귀가, 지금은 제품의 종류를 계산할 경우 어떻게 분석 할, MAXDATA [j는] 우리가 내가 번째 글, 다음의 최대 값 또는 내가 "없습니다 할"만약 내가-1 J, 상품의 종류의 무게에 해당하는 가장 큰 값이다 -1 우리는 "원하는"경우, 문서에 대응하는 최대 값 i 번째 문서, 이것은 [I] 용량 중량을 차감 한 번 항목 전에 I-1의 최대 값에 대응하고, [I]의 값을 추가한다. 판정에 대응하는 데이터가 완료되기 때문에,이 최대 값으로되는 큰 선택이 두 값이 너무 새로운 데이터 소용이 해당 위치에이 중첩하지 않을 수있다, 즉 MAXDATA [I] = 맥스 (MAXDATA [J], 맥스 [J 웨이트 [I] 값 + [I])
코어 코드 쿠폰

    //递推(迭代) 滚动数组
    int f[100] = { 0 };    //f[j]储存前一轮各个重量下最大价值
    for (int i = 1; i <= n; i++) {       //枚举种类
        for (int  j = totalweight; j >= 0; j--){   //算前n种的各个重量下最大价值
            int next_w = j - weight[i];      //“要”这个物品的情况下对应的下标
            if (next_w < 0) next_w = 0;   //防止下标越界
            if (weight[i] > j)
                f[j] = f[j];    //超重则最大价值等于前一轮对应容量下的最大价值,直接“不要”
            else 
                f[j] = max(f[j], f[next_w] + value[i]);
                        if(i==n) break;      //最后一个物品只需要算一个totalweight的就够了
        }
    }//最终得到的f[totalweight]就是n个物品用整个背包去装能得到的最大价值。

내가이 모든 이해를 처리 할 수있을 것입니다 =이 프로세스의 이해, 한 그들이 얻을으로 난 = 1. 임의의 예가 될 수있다 : (12)의 가정하자 배낭 용량
| 문서 | 품질 | 숫자 값
. 1.8 10
2 6.5 B.
3. 4. 5시켰다.

  • 용량이 8 (10)보다 작지 않을 때 첫 번째에서 시작, 우리는 다른 그 데이터 F []을 10 이상 이후에 모두 0이다는 것,하기 화학식 F [0이고, 그 최대 값을 찾을 J = 최대 (0,0 + 8 ) 은 새로운 F를 얻을 수있다 []
    . F [] = {0 0 0 0 0 0 0 0 0 0 8 8 8 ......
  • 다음 두 번째 항목 B를 찾고,
    총 용량은 12, F [12]가있는 최대 (F = [12], F [12-6] +5) F [12] 전방 별 8 같음, F [6] = 0,이 용량의 범위 내에서, 우리는 선택할 것이다 것이 분명하다 "할 일을하지."
    등까지 우리는 {0 0 0 [A 얻을 F] = 수 우리가 "가"를 선택한다 5 <J <10 찾을 수 ...... 6 6 6 6 8 8 8 0 0 0}
  • 이 인식되지 않은 경우, 문서가 제 C 보면 계속
    J = 12, F [12] 최대 = 때 정확한 개념 앞 ( F [12], F [12-5] +4) 우리가 F를 발견 [12] = 8 <F [7] +5 = 11; 우리는 "을"선택 그래서
    이 그것의 마지막이기 때문에, 우리는 세 가지 항목을 가지고있다 (12)의 용량을 카운트 다운 계속 쓸모가 최대 값은 11이었다
    여기에 반복 알고리즘이도 완성 설명하기! !

    잡담

    처음이 블로그를 작성, 나는 논리적 오류와 버그가있을 수 있습니다, 자신의 이해에 따라이 내용이 기록, 가장 중요한 것은 자신의 검토 지식은 여기에 배운하기 위해 여전히 매우 흥미로운 느낌, 그리고 문제가 계속 발견하는 경우 의견을 알려주십시오.

    전체 코드 내 GitHub의 참조

추천

출처www.cnblogs.com/sjh001/p/12041686.html