DP
题意
给你n个物品,你有一个容量为W的背包,每一个物品都有它的重量和价值,让你从n个中选取若干个,使得总重量不超过背包的上限,而且使得价值最大。
题解
原本是贪心,太繁了,用DP
i是遍历到前i个时,j是转换后重量和,k就代表已经选了k个,这重量加上k * w1就等于原来的重量
dp代表最后的价值
解释
i是目前范围是1-i,j表示(转化后的重量)的总和是j,k表示目前已经选择了k个,比如如果w1=5,
我选了一个w[1]=5,w[2]=6两个,那就是dp[2][1][2]这个状态
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF = 1e9 + 7;
const ll mod = 1e9 + 7;
const int MAX = 3e2 + 100;
ll w[MAX], v[MAX];
ll dp[MAX][MAX][MAX];
int main() {
int n, m;
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++) {
scanf("%lld %lld", &w[i], &v[i]);
}
ll w1 = w[1];
for(int i = 1; i <= n; i++) {
w[i] -= w1;
}
for(int i = 1; i <= n; i++) {
for(int j = 0; j <= n; j++) {
for(int k = 1; k <= n; k++) {
if(j - w[i] >= 0) {
dp[i][j][k] = max(dp[i - 1][j][k], dp[i - 1][j - w[i]][k - 1] + v[i]);
}
else {
dp[i][j][k] = max(dp[i - 1][j][k], dp[i][j][k]);
}
}
}
}
ll ans = 0; //一定是0
for(int j = 0; j <= n; j++) {
for(int k = 1; k <= n; k++) {
if(j + k * w1 <= m)
ans = max(ans, dp[n][j][k]);
}
}
printf("%lld\n", ans);
}
闲话
这B题我的思路还是有问题
这场个人赛,我很快出了A和C,因为都是没有什么算法要求的思维题(C的一血)
我的D题没带字典,有些关键字我看不大懂,就迷迷糊糊写了一发并查集的(后来队友也说是这么做的),wa3,然后不确定是不是题目读错,就不看了
可是B我还没有写出来,最终还是两题
我的代码实现能力太差了,以及读题能力
要不是有两道思维题,就要爆零了
无论如何,这个学期的训练就结束了。暑假加油!