1. 洛谷 P2871 [USACO07DEC] Charm Bracelet S
题目链接:洛谷 P2871
01 背包模板题,不过多解释。
#include
using namespace std;
constexpr int N = 3500, M = 13000;
int n, m, w[N], d[N], dp[M];
int main() {
ios::sync_with_stdio(false); cin.tie(nullptr);
cin >> n >> m;
for (int i = 1; i <= n; i++) cin >> w[i] >> d[i];
memset(dp, 0, sizeof(dp));
for (int i = 1; i <= n; i++)
for (int j = m; j >= w[i]; j--) dp[j] = max(dp[j], dp[j - w[i]] + d[i]);
cout << dp[m] << endl;
return 0;
}
2. P1855 榨取kkksc03
题目链接:洛谷 P1855
跟前面的模板题很像,只是 d p dp dp 数组从一维变成了二维。设 d p j , k dp_{j, k} dpj,k 为考虑到第 i i i 个愿望,需要金钱为 j j j,需要时间为 k k k 最多可以实现的愿望个数,那么 d p j , k = m a x ( d p j , k , d p j − m , k − t + 1 ) dp_{j, k} = max(dp_{j, k}, dp_{j - m, k - t} + 1) dpj,k=max(dpj,k,dpj−m,k−t+1)
#include
using namespace std;
#define int long long
int n, M, T, dp[205][205];
signed main() {
ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
cin >> n >> M >> T;
for (int i = 1; i <= n; i++) {
int m, t;
cin >> m >> t;
for (int j = M; j >= m; j--)
for (int k = T; k >= t; k--) dp[j][k] = max(dp[j][k], dp[j - m][k - t] + 1);
}
cout << dp[M][T] << endl;
return 0;
}
1. P1616 疯狂的采药
题目链接:洛谷 P1616
完全背包模板题,不过多解释。
#include
using namespace std;
#define int long long
constexpr int T = 1e7 + 10, M = 1e4 + 10;
int t, m, a[M], b[M], dp[T];
signed main() {
ios::sync_with_stdio(false); cin.tie(nullptr);
cin >> t >> m;
for (int i = 1; i <= m; i++) cin >> a[i] >> b[i];
memset(dp, 0, sizeof(dp));
for (int i = 1; i <= m; i++)
for (int j = a[i]; j <= t; j++) dp[j] = max(dp[j], dp[j - a[i]] + b[i]);
cout << dp[t] << endl;
return 0;
}
1. P1776 宝物筛选
题目链接:洛谷 P1776
多重背包模板题,二进制分组优化
#include
using namespace std;
#define int long long
const int N = 1e6 + 10;
int n, W, cnt = 0, w[N], v[N], dp[N];
signed main() {
ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
cin >> n >> W;
for (int i = 1; i <= n; i++) {
int a, b, c;
cin >> a >> b >> c;
int res = 1;
while (c >= res) {
cnt++;
v[cnt] = res * a, w[cnt] = res * b;
c -= res;
res <<= 1;
}
if (c) {
cnt++;
v[cnt] = a * c, w[cnt] = b * c;
}
}
for (int i = 1; i <= cnt; i++) {
for (int j = W; j >= w[i]; j--) dp[j] = max(dp[j], dp[j - w[i]] + v[i]);
}
cout << dp[W] << endl;
return 0;
}
核心思想:将不同种类的背包分别处理。
1. P1833 樱花
题目链接:洛谷 P1833
混合背包模板题,与前面几种背包不同的是,需要对集中不同类型的背包进行分类处理。
#include
using namespace std;
#define int long long
int n, T, dp[1005];
string ts, te;
signed main() {
ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
cin >> ts >> te >> n;
int hs = 0, ms = 0, he = 0, me = 0, i;
for (i = 0; i < ts.size() && ts[i] != ':'; i++) hs = hs * 10 + ts[i] - '0';
for (i = i + 1; i < ts.size(); i++) ms = ms * 10 + ts[i] - '0';
for (i = 0; i < te.size() && te[i] != ':'; i++) he = he * 10 + te[i] - '0';
for (i = i + 1; i < te.size(); i++) me = me * 10 + te[i] - '0';
T = (he - hs) * 60 + me - ms;
for (int i = 1; i <= n; i++) {
int t, c, p;
cin >> t >> c >> p;
if (!p)
for (int j = t; j <= T; j++) dp[j] = max(dp[j], dp[j - t] + c);
else {
for (int k = 1; k <= p; k *= 2) {
int tt = t * k, cc = c * k;
for (int j = T; j >= tt; j--) dp[j] = max(dp[j], dp[j - tt] + cc);
p -= k;
}
if (p) {
int tt = t * p, cc = c * p;
for (int j = T; j >= tt; j--) dp[j] = max(dp[j], dp[j - tt] + cc);
}
}
}
cout << dp[T] << endl;
return 0;
}