动态规划--背包问题
题目大意:
有 $n$ 个物体 第 $i$ 个物体的体积为 $wi$ 价值为 $vi$ 背包容积为 $W$ 求所有挑选方案中价值总和的最大值
解法1:
针对每个物品是否放入背包进行搜索
时间复杂度:$O(2^n)$
代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
int n, W;
int w[maxn], v[maxn];
int rec(int i, int j) {
int res;
if(i == n)
res = 0;
else if (j < w[i])
res = rec(i + 1, j);
else
res = max(rec(i + 1, j), rec(i + 1, j - w[i]) + v[i]);
return res;
}
void solve() {
printf("%d\n", rec(0, W));
}
int main() {
scanf("%d%d", &n, &W);
for(int i = 0; i < n; i ++)
scanf("%d%d", &w[i], &v[i]);
solve();
return 0;
}
解法2:
记忆化搜索,把第一次计算结果存到 $dp$ 数组中,第二次之后如果有同样的 $i, j$ 直接返回
时间复杂度:$O(n * W)$
代码:
#include <bits/stdc++.h>
using namespace std;
int n, W;
int w[11111], v[11111];
int dp[11111][11111];
int rec(int i, int j) {
if(dp[i][j] >= 0)
return dp[i][j];
int res;
if(i == n)
res = 0;
else if(j < w[i])
res = rec(i + 1, j);
else
res = max(rec(i + 1, j), rec(i + 1, j - w[i]) + v[i]);
return dp[i][j] = res;
}
void solve() {
memset(dp, -1, sizeof(dp));
printf("%d\n", rec(0, W));
}
int main() {
scanf("%d%d", &n, &W);
for(int i = 0; i < n; i ++)
scanf("%d%d", &w[i], &v[i]);
solve();
return 0;
}
解法3:
dfs
时间复杂度:$O(2^n)$
代码:
#include <bits/stdc++.h>
using namespace std;
int n, W;
int w[11111], v[11111];
int dfs(int i, int j, int sum) {
int res;
if(i == n)
res = sum;
else if(j < w[i])
res = dfs(i + 1, j, sum);
else
res = max(dfs(i + 1, j, sum), dfs(i + 1, j - w[i], sum + v[i]));
return res;
}
int main() {
scanf("%d%d", &n, &W);
for(int i = 0; i < n; i ++)
scanf("%d%d", &w[i], &v[i]);
int num = dfs(0, W, 0);
printf("%d\n", num);
return 0;
}
解法4:
动态规划 不写递归函数,直接用递推式把各项的值计算出来(如果多组输入 $dp$ 需要初始化)
时间复杂度:$O(n * W)$
代码1:
#include <bits/stdc++.h>
using namespace std;
int n, W;
int w[11111], v[11111];
int dp[11111][11111];
void solve() {
for(int i = n - 1; i >= 0; i --) {
for(int j = 0; j <= W; j ++) {
if(j < w[i])
dp[i][j] = dp[i + 1][j];
else
dp[i][j] = max(dp[i + 1][j], dp[i + 1][j - w[i]] + v[i]);
}
}
printf("%d\n", dp[0][W]);
}
int main() {
scanf("%d%d", &n, &W);
for(int i = 0; i < n; i ++)
scanf("%d%d", &w[i], &v[i]);
solve();
return 0;
}
代码2:
#include <bits/stdc++.h>
using namespace std;
int n, W;
int w[11111], v[11111];
int dp[11111][11111];
void solve() {
for(int i = 0; i < n; i ++) {
for(int j = 0; j <= W; j ++) {
if(j < w[i])
dp[i + 1][j] = dp[i][j];
else
dp[i + 1][j] = max(dp[i][j], dp[i][j - w[i]] + v[i]);
}
}
printf("%d\n", dp[n][W]);
}
int main() {
scanf("%d%d", &n, &W);
for(int i = 0; i < n; i ++)
scanf("%d%d", &w[i], &v[i]);
solve();
return 0;
}
代码3:
#include <bits/stdc++.h>
using namespace std;
int n, W;
int w[11111], v[11111];
int dp[11111][11111];
void solve() {
for(int i = 0; i < n; i ++) {
for(int j = 0; j <= W; j ++) {
dp[i + 1][j] = max(dp[i][j], dp[i + 1][j]);
if(j + w[i] <= W)
dp[i + 1][j + w[i]] = max(dp[i + 1][j + w[i]], dp[i][j] + v[i]);
}
}
printf("%d\n", dp[n][W]);
}
int main() {
scanf("%d%d", &n, &W);
for(int i = 0; i < n; i ++)
scanf("%d%d", &w[i], &v[i]);
solve();
return 0;
}

浙公网安备 33010602011771号