1、在贴代码之前,有几点是需要知道的
设F[i][j]表示出在前i种物品中选取若干件物品放入容量为j的背包所得的最大价值。那么对于第i种物品的出现,我们对第i种物品放不放入背包进行决策。如果不放那么F[i][j]=F[i-1][j];如果确定放,背包中应该出现至少一件第i种物品,所以F[i][j]种至少应该出现一件第i种物品,即F[i][j]=F[i][j-C[i]]+W[i]。为什么会是F[i][j-C[i]]+W[i]?因为F[i][j-C[i]]里面可能有第i种物品,也可能没有第i种物品。我们要确保F[i][j]至少有一件第i件物品,所以要预留C[i]的空间来存放一件第i种物品。
2、
完全背包与01背包不同之处在于,每件物品的数量都是无限的。
在处理的时候:01背包是后面的前面dp, 完全背包是从前面到后面dp
3、以下是hdu 3217 的代码:
/*
* 3217.cpp
*
* Created on: 2013年7月29日
* Author: Administrator
*/
#include <iostream>
__int64 dp[1100][1100];
// __int64用于表示64位整数
using namespace std;
const int Max = 20;
struct Two_CostPackage {
int x;
int y;
int val;
} p[Max];//用来存储三角形可能的种类
int main() {
int i, j, k, t, xi, yi, n;
cin >> t;
while (t--) {
cin >> n >> xi >> yi;
for (i = 0; i < n; ++i) {
cin >> p[i].x >> p[i].y >> p[i].val;
}
memset(dp, 0, sizeof(dp));
for (j = 1; j <= xi; ++j) {//j是用来标记长度的变量
for (k = 1; k <= yi; ++k) {//k是用来标记宽度的变量
for (i = 0; i < n; ++i) {
int x = p[i].x;
int y = p[i].y;
int val = p[i].val;
if (j >= x && k >= y) {//如果j大于长x,k大于宽y(及存在符合条件的矩形)
dp[j][k] = max(dp[j][k],
max(dp[j - x][y] + dp[j][k - y],
dp[j - x][k] + dp[x][k - y]) + val);
}
/**
* 交换长x和宽y,实现第二种切割方式.
* x,y是题目中其中一种指定三角形的长和宽.
*/
swap(x, y);
if (j >= x && k >= y) {
dp[j][k] = max(dp[j][k],
max(dp[j - x][y] + dp[j][k - y],
dp[j - x][k] + dp[x][k - y]) + val);
}
}
}
}
cout<<dp[xi][yi]<<endl;
}
}