質問:現在4つのアイテムがあります。バックパックの総容量は8で、バックパックが保持できる最大値はいくつですか。
商品番号:1 2 3 4
アイテムボリューム:2 3 4 5
アイテム値:3 4 5 6
番号\容量 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
1 | 0 | 0 | 3 | 3 | 3 | 3 | 3 | 3 | 3 |
2 | 0 | 0 | 3 | 4 | 4 | 7 | 7 | 7 | 7 |
3 | 0 | 0 | 3 | 4 | 5 | 7 | 8 | 9 | 9 |
4 | 0 | 0 | 3 | 4 | 5 | 7 | 8 | 9 |
フォームに記入するためのアイデア:
- 現在のアイテムをロードできない場合、最初のn個のアイテムの最適な組み合わせは、最初のn-1個のアイテムの最適な組み合わせと同じです。
- 現在のアイテムをロードできます
1.現在のアイテムをロードし、バックパック内の現在のアイテムに対応するスペースを予約します。最初のn-1アイテムと現在のアイテムの値の最適な組み合わせは、合計値
2です。現在のアイテムがロードされていない場合、前のn個のアイテムの最適な組み合わせは最初のn-1個のアイテムの最適な組み合わせと同じです。3
。現在の最適な組み合わせの値として1と2の大きい方の値を選択します。
バックパックの問題に戻る:バックパック
の合計値を最大化する場合、どのアイテムがバックパックに含まれているのか
分析:現在の値は10です。アイテム4がインストールされていない場合、現在の値(10)は最初の3つのアイテム(9)の合計値と同じである必要があります。明らかに10と9は違うので、アイテム4を入れました。
概要:後ろから前に振り返ると、最初のn個のアイテムの最適な組み合わせの値が、最初のn-1個のアイテムの最適な組み合わせの値と同じである場合、n番目のアイテムがにロードされていないことを意味します。バックパック。それ以外の場合は、バックパックにロードされます。
コード
// Dynamic programming
/* 物品编号 1 2 3 4
体积 2 3 4 5
价值 3 4 5 6*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int weight[5] = {0, 2, 3, 4, 5};
int value[5] = {0, 3, 4, 5, 6};
int dp[5][9] = {0};
int object[5];
int max(int x, int y){
return x>y?x:y;
}
void printDp() {
for(int i=0;i<5;i++) {
for (int j=0; j<9; j++) {
printf("%d\t",dp[i][j]);
}
printf("\n");
}
}
int dpWrite() {
memset(dp,0,sizeof(dp));
for (size_t i = 1; i < 5; i++) //物品编号
{
for (size_t j = 1; j < 9; j++) // 背包容量
{
if(weight[i]>j) //物品放不下
dp[i][j] = dp[i-1][j];
else
dp[i][j]= max(dp[i-1][j], value[i] + dp[i-1][j-weight[i]]);
}
}
printDp();
}
// 背包回溯问题
void Find(int i, int j) {
if (i == 0) {
for (int ii=0; ii<5; ii++) {
printf("%d ",object[ii]);
}
return;
}
// 没装入背包
if (dp[i][j] == dp[i - 1][j]) {
object[i] = 0;
Find(i-1, j);
}
// 装入背包
else if (dp[i][j] == value[i] + dp[i - 1][j - weight[i]]) {
object[i] = 1;
Find(i-1, j-weight[i]);
}
}
int main() {
dpWrite();
Find(4, 8);
printf("\n(%d, %d)===>[",4, 8);
for (int i=0; i<5; ++i) {
printf("%d ", object[i]);
}
printf("]\n");
}