[예약] [01] 동적 프로그래밍 배낭 문제 (이해하기 쉽게, 슈퍼에 기초하여 설명)

재판 : https://blog.csdn.net/qq_38410730/article/details/81667885

항목을 n 개의있다, 그들은 어떻게 배낭에 항목 합계의 최대 값을 가지고 얻을 수있는 배낭, 기존의 용량을 제공, 자신의 볼륨과 가치가?

예 : 수 = ​​4 = 8 용량 설명 및 이해를 용이하게하기 위해서, 다음의 예, 즉, 치환의 구체적 수치와 함께 최초로

I (항목 수) 1 4
w (부피 기준) 4 5
V (값) 4 5 6

 

일반 아이디어

01 배낭 문제를 동적 프로그래밍 문제 해결 단계를 찾기 위해 (문제 추상화, 모델은 용액 조성물을 찾아, 큰 문제가 재발 관계, 지침의 작은 문제를 찾고, 최적의 원리를 충족 여부를 결정하기 위해, 제약 조건을 찾아) 다음 최적해와 용액 조성물, 및 코드 물품.

동적 프로그래밍의 원리

유사 동적 프로그래밍과 격차와 작은 문제가 큰 문제를 분할하고, 정복, 사소한 문제가 재발 관계를 발견하여 큰 문제는 작은 문제를 해결하고, 궁극적으로 원래의 문제를 해결하는 효과를 얻을 수 있습니다. 그러나 차이는 분열과 정복은, 기억이있을 것이다 이중 계산 하위 문제 및 하위 하위 문제 및 동적 프로그래밍에 여러 번입니다,이다 우리는 새로운 문제에 필요한 하위 질문에 대답 기록 아래 해결 된 테이블 모두 작성하여 하위 문제를 직접 때문에 시간을 절약, 중복 계산을 피하기 위해, 추출하는 데 사용할 수 있으므로 문제 후 최적의 원리를 충족하기 위해 동적 프로그래밍의 핵심 문제가이 양식을 작성하고, 양식이 완료 될 때, 최적의 솔루션은 것입니다 찾을 수 있습니다.

최적 원리는 최적의 동적 프로그래밍 원리에 기초하여이 최적의 결정 순서 "와 같은 자연의 다단 의사 결정 프로세스를 의미이다 없이 초기 상태와 초기 결정의 관점에서 임의의 결정으로 인해 이전하는 상태 최적의 전략을 구성해야하는 의사 결정 시퀀스의 모든 단계 다음에 . "

배낭 문제 해결 과정

어떤 변수를 정의 우선, 설명의 편의를 위해,이 문제를 해결하기 전에 : VI는 i 번째 문서의 값을 나타내고, WI는 제 i 벌키 항목 V의 정의를 나타내고, (I, J) : 현재 배낭 용량 J, 대부분의 i 번째 문서 전 양호한 값의 조합에 대응하는 배낭 문제 추상화 (X1은 X2가, ..., Xn에 동시에 , 자이 0 또는 1, i 번째 항목을 나타내는 상기 선택 또는 선택되지 않는다).

1 모델, 즉 최대 (V1X1 V2X2 + + ... + VnXn)를 발견;

2, 제약 조건을 찾으려면, W1X1 + W2X2 + ... + WnXn <용량;

3, 재발 관계를 찾고 , 상품의 얼굴은 두 가지 가능성이있다 :

  • 패킷 물품 착용감의 체적 용량보다 작고,이 경우에는 I-1 번째의 키의 값은 이전과 동일, 즉 V (I, J) = V (I-1, J);
  • I- (제품을 저장할 수있는 충분한 용량이 있지만, 반드시 설치되어 있지 도달이 최적 값을 가지므로 최적의 선택은,로드 및로드되지 즉 V (I, J) = {V 최대 사이 1, J), V (I-1, JW (I)) + V (I)}.

V는 (I-1, j)에로드되지 나타내고, V (I-1, JW (I)) + V (i)가 설치되어, i 번째의 상품이고, 배낭 용량은 W (i)를 감소하지만, 값 (V)을 증대 (I);

그것은 재발의 관계를 다음과 같습니다 :

  • J <w (I) V (I, J) = V (I-1, J)
  • J> = w (I) V (I, J) = {V 맥스 (I-1, J), V (I-1, JW (I)) + V (I)}

사건이 해결해야 할 필요성 저장할 수있는 이유를 설명해야한다 (이이 문제의 핵심입니다!)

당신이 V (I, J)의 상태에 도달하려면 여러 가지 방법이 있다는 것을 이해 할 수 있는가?

물론 두 개의, 제 번째로 로딩되지 않는 난 항목 그것에로드 우선 항목이다. 잘 이해 이동을 장착하지, V는 (I-1, J)이다 ; 에로드하는 방법을 이해하기 위해? 항목이 난에로드 된 경우, 이전에 로딩 상태 무엇인가, 그것은해야합니다 V (I-1, JW ( I)). 최적의 원리 때문에, V (I-1 (위에서 언급) JW (Ⅰ))는 상기 결정에 의해 야기 된 상태이며, 결정은 나중에 최적 정책을 구성한다. 두 가지 경우, 가장 좋은 결과를 비교 하였다.

4, 충전 우선, V (0, J)를 경계 조건을 초기화 V = (I 0) = 0;

그런 다음 라인으로 양식 줄에 입력 :

  • 이러한 I = 1, J = 1, 1 = 2, V, W (1) = 3, J있다 같은 <w (1), 그래서 V (1,1) = V (1-1,1) = 0 ;
  • 또 다른 예는 w는 I = 1, J = 2, (1) = (2), V (1) = 3 = w (1), 그래서 V (1,2) = {V 맥스 (1-1,2) J 존재 , V (1-1,2-w (1)) + V (1)} = {0,0 최대 + 1} = 3;
  • 이러한 상황에서, ((4), 그래서 V (4,8) = 최대 {V w (4) = 5 (V) (4) = 6있다 J w 마지막으로, I = 4, J = 8> 채우는 4-1,8) V는 (4-1,8-w (4)) + V (4)} = 최대 {9,4} + 6 = 10 ......

아래 그림과 같이 그래서 테이블이 완료되었습니다

5, 즉 폼을 완료하는 데 최적의 솔루션은 V (번호, 용량) = V (4,8) = 10이다.

 

코드 구현

동적 계획 및 네 개의 상품, 그러나 우리의 배열 요소는 다섯 만든 있지만, 이전에 비교 될 수있다.


  
  
  1. # 포함 <iostream>
  2. 사용하는 네임 스페이스 표준을 ;
  3. #이 포함 <알고리즘>
  4. int 형 ) (
  5. {
  6. INT W [ 5. = {] 0 , 2 , 3. , 4. , 5. } 상품 부피 2,3,4,5 //
  7. INT의 V [ . 5 ] = { 0 , 3. , 4. , 5. , 6. } 값 // 무역 3,4,5,6-
  8. INT bagV = 8. ; // 크기의 배낭
  9. INT DP [ 5. ] [ 9. = {{] 0 }} // 동적 프로그래밍 테이블
  10. 위한 ( int로 I = 1 ; i가 = < 4 ; 나는 ++) {
  11. ( INT의 J = 1 ; J <= bagV, J ++) {
  12. 만약 (j <w [I])
  13. - DP는 [I]는 [J]를 DP [I = 1 ] [J]를]
  14. 그밖에
  15. DP [I] [J] = 최대 (DP [I - 1 ] [J], DP [I - 1 ] [J - w [I] + V [I]);
  16. }
  17. }
  18. // 출력 동적 프로그래밍 테이블
  19. 위한 ( int로 I = 0 ; i가 < 5 ; 내가 ++) {
  20. ( INT의 J = 0 ; J < 9 , J ++) {
  21. COUT << DP [I] [J] << ' ;
  22. }
  23. COUT << ENDL ;
  24. }
  25. 반환 0 ;
  26. }

 

배낭 문제 최적의 솔루션 되돌아

배낭 문제 최적의 솔루션을 추구의 양식을 작성 수있는 다음과 같은 원칙을 상기 방법에 의해 얻을 수 있지만, 상품 구성하여 최적의 솔루션, 그것은 해결책을 찾기 위해 되돌아의 구성에 따라 최적의 솔루션입니다 모르겠어요, 따라 해결 방법 :

  • V (I, J) = V (I-1, j)는, i 번째 상품이 V (I-1, J)로 프로세스를 리턴 선택되어 있지 않은 것을 나타낸다
  • V (I, J) = V (I-1, JW (I)) + (I)의 i 번째 제품이 최적의 솔루션의 일부를 구성하고, 제품을 설치 설명해 우리가 패키지를 반환해야 V 제품 전에, 즉 다시 V (I-1, JW (I))에;
  • 나는 = 0 종료 날짜에 통과되어, 조성물은 모든 솔루션을 찾을 수 있습니다.

예를 들어, 위의 예를 보자

  • 최적해 V (4,8) = 10, 및 V (4,8)! = V (3,8)이있다 V (4,8) = V (3,8-w (4)) + (V) (4) = V (3,3) + 6 = 4 네 번째 항목이 선택되고, 그래서 = 10 + 6, 다시 V에 (3,8-w (4)) = V (3,3);
  • 세 번째 항목이 선택되지 않도록 V는 (3,3) 위로 V (2,3)에, V (2,3) = 4 =있다;
  • 그리고 V (2,3)! = V (1,3)이있다 V (2,3) = V (1,3- w (2)) + V (2) = V (1,0) + 4 = + 4 번째 항목이 선택되도록 4 = 0, 다시 V에 (1,3- w (2)) = V (1,0);
  • V가 (1,0) = V (0,0) = 0이므로, 첫 번째 항목이 선택되지 않는다.

 

코드 구현

배낭 문제 자세한 코드의 최종 버전은 다음을 달성하기 위해 :


  
  
  1. # 포함 <iostream>
  2. using namespace std;
  3. #include <algorithm>
  4. int w[ 5] = { 0 , 2 , 3 , 4 , 5 }; //商品的体积2、3、4、5
  5. int v[ 5] = { 0 , 3 , 4 , 5 , 6 }; //商品的价值3、4、5、6
  6. int bagV = 8; //背包大小
  7. int dp[ 5][ 9] = { { 0 } }; //动态规划表
  8. int item[ 5]; //最优解情况
  9. void findMax() { //动态规划
  10. for ( int i = 1; i <= 4; i++) {
  11. for ( int j = 1; j <= bagV; j++) {
  12. if (j < w[i])
  13. dp[i][j] = dp[i - 1][j];
  14. else
  15. dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - w[i]] + v[i]);
  16. }
  17. }
  18. }
  19. void findWhat(int i, int j) { //最优解情况
  20. if (i >= 0) {
  21. if (dp[i][j] == dp[i - 1][j]) {
  22. item[i] = 0;
  23. findWhat(i - 1, j);
  24. }
  25. else if (j - w[i] >= 0 && dp[i][j] == dp[i - 1][j - w[i]] + v[i]) {
  26. item[i] = 1;
  27. findWhat(i - 1, j - w[i]);
  28. }
  29. }
  30. }
  31. void print() {
  32. for ( int i = 0; i < 5; i++) { //动态规划表输出
  33. for ( int j = 0; j < 9; j++) {
  34. cout << dp[i][j] << ' ';
  35. }
  36. cout << endl;
  37. }
  38. cout << endl;
  39. for ( int i = 0; i < 5; i++) //最优解输出
  40. cout << item[i] << ' ';
  41. cout << endl;
  42. }
  43. int main()
  44. {
  45. findMax();
  46. findWhat( 4, 8);
  47. print();
  48. return 0;
  49. }

추천

출처blog.csdn.net/mad_sword/article/details/92816089