举个例子,你要去一个水果摊拿水果,每种水果都有对应的两种属性:占用的体积V和蕴含的价值W。而你的背包体积为N。
老板说:每种水果只能拿一个!因此对于咱们肯定得想一种搭配方式使得拿的水果总体积不超过背包容积,但是价值总和达到最大!
第一行两个整数,N,V,用空格隔开,分别表示物品数量和背包容积。
接下来有 N 行,每行两个整数 vi,wi,用空格隔开,分别表示第 i 件物品的体积和价值。
数据范围:
00 输入样例:
4 5
1 2
2 4
3 4
4 5
#include
#include
#include
int main() {
int arr[1000][2];
int v, n, *status[1000];
while (scanf("%d %d", &n, &v) != EOF) {
for (int i = 1; i <= n; i++) { // 任意物品i都需要依赖前一物品i-1的状态,为减少后续DP过程的计算,物品和状态都从1开始
scanf("%d %d", &arr[i][0], &arr[i][1]);
status[i] = (int*)malloc(sizeof(int) * (v + 1));
}
status[0] = (int*)malloc(sizeof(int) * (v + 1));
memset(status[0], 0x00, sizeof(int) * (v + 1)); // 初始化物品0的状态
for (int i = 1; i <= n; i++) {
status[i][0] = 0;
for (int j = 1; j <= v; j++) {
status[i][j] = status[i - 1][j];
if (j >= arr[i][0]) {
status[i][j] =
status[i][j] > (status[i - 1][j - arr[i][0]] + arr[i][1])
? status[i][j]
: (status[i - 1][j - arr[i][0]] + arr[i][1]);
}
}
}
printf("%d\n", status[n][v]);
}
}
从状态的推导图中,可以看出以下2点:
针对以上3点,做出以下优化:
#include
int main() {
int arr[1000][2];
int v, n, status[1000] = {0};
while (scanf("%d %d", &n, &v) != EOF) {
for (int i = 1; i <= n; i++) {
scanf("%d %d", &arr[i][0], &arr[i][1]);
}
for (int i = 1; i <= n; i++) {
for (int j = v; j >= arr[i][0]; j--) {
status[j] =
status[j] > (status[j - arr[i][0]] + arr[i][1])
? status[j]
: (status[j - arr[i][0]] + arr[i][1]);
}
}
printf("%d\n", status[v]);
}
}