多结果的背包问题,P1509 找啊找啊找GF
P1509 找啊找啊找GF - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
有一种背包问题,他不仅问你最大价值,还会问你最大价值的时候花费的时间最小是多少(当然,不一定是最小时间,这只是举个例子)
下面便是一道这样的例题:
题目描述
sqybi 现在看中了 n 个 MM,我们不妨把她们编号 11 到 n。请 MM 吃饭是要花钱的,我们假设请 i 号 MM 吃饭要花 rmb[i] 块大洋。而希望骗 MM 当自己 GF 是要费人品的,我们假设请第 i 号 MM 吃饭试图让她当自己 GF 的行为(不妨称作泡该 MM)要耗费 rp[i] 的人品。而对于每一个 MM 来说,sqybi 都有一个对应的搞定她的时间,对于第 i 个 MM 来说叫做time[i]。sqybi 保证自己有足够的魅力用time[i] 的时间搞定第 i 个 MM ^_^。
sqybi 希望搞到尽量多的 MM 当自己的 GF,这点是毋庸置疑的。但他不希望为此花费太多的时间(毕竟七夕赛的题目还没出),所以他希望在保证搞到 MM 数量最多的情况下花费的总时间最少。
sqybi 现在有 m 块大洋,他也通过一段时间的努力攒到了 r 的人品(这次为模拟赛出题也攒 rp 哦~~)。他凭借这些大洋和人品可以泡到一些 MM。他想知道,自己泡到最多的 MM 花费的最少时间是多少。
注意 sqybi 在一个时刻只能去泡一个 MM ——如果同时泡两个或以上的 MM 的话,她们会打起来的…
输入格式
输入的第一行是 n,表示 sqybi 看中的 MM 数量。
接下来有 n 行,依次表示编号为 1,2,3,…,n 的一个 MM 的信息。每行表示一个 MM 的信息,有三个整数:rmb,rp 和 time。
最后一行有两个整数,分别为 m 和 r。
输出格式
你只需要输出一行,其中有一个整数,表示 sqybi 在保证 MM 数量的情况下花费的最少总时间是多少。
输入输出样例
输入 #1复制
4 1 2 5 2 1 6 2 2 2 2 2 3 5 5
输出 #1复制
13
说明/提示
sqybi 说:如果题目里说的都是真的就好了…
sqybi 还说,如果他没有能力泡到任何一个 MM,那么他就不消耗时间了(也就是消耗的时间为 00),他要用这些时间出七夕比赛的题来攒 rp…
【数据规模】
对于 20%20% 的数据,1≤�≤101≤n≤10;
对于 100%100% 的数据,1≤���≤1001≤rmb≤100,1≤��≤1001≤rp≤100,1≤����≤10001≤time≤1000。
对于 100%100% 的数据,1≤�,�,�≤1001≤m,r,n≤100。
解析:
这道题给出了两个限制条件,或者说两个体积限制:rmb,rp
价值是妹子的个数,除此之外我们还要求最大价值时的最小时间花费;
由于这里有两种限制,所以我们很容易想到用二维数组来表示(这里就不过多介绍了,这道题一定要有基础才能做)
由于题目让我们就:最大妹子个数,最小时间花费;
所以我们要分配两个数组,f和dp,f的属性为最大妹子个数,dp的属性为最小时间花费;
又因为题目说的是最大妹子个数的情况下的最小时间花费,
所以f的优先级高于dp;
f的状态转移方程:
f[j][k]=max(f[j][k],f[j-a[i]][k-b[i]]+1);
dp的状态转移方程:
情况一:f[j][k]==f[j-a[i]][k-b[i]]+1
dp[j][k]=min(dp[j][k],dp[j-a[i]][k-b[i]]+c[i]);
情况二:f[j][k]<f[j-a[i]][k-b[i]]+1
dp[j][k]=dp[j-a[i]][k-b[i]]+c[i];
注意:这里没有 f[j][k]>f[j-a[i]][k-b[i]]+1
因为这个情况在之前的 f[j][k]>f[j-a[i]][k-b[i]]+1 就已经处理过了
而且千万不能写成:
当 f[j][k]>=f[j-a[i]][k-b[i]]+1
dp[j][k]=min(dp[j][k],dp[j-a[i]][k-b[i]]+c[i]);
当 f[j][k]>f[j-a[i]][k-b[i]]+1时,
f[j-a[i]][k-b[i]]的状态无法转移到 f[j][k]
同样的,dp[j-a[i]][k-b[i]]的状态无法转移到 dp[j][k]
#include<iostream>
#include<set>
#include<vector>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<map>
#include<math.h>
using namespace std;
typedef long long LL;
const int N = 105;
int f[N][N], dp[N][N];
int a[N], b[N], c[N];
int n, m, r;
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d%d%d", &a[i],&b[i],&c[i]);
}
scanf("%d%d", &m, &r);
for (int i = 1; i <= n; i++) {
for (int j = m; j >= a[i]; j--) {
for (int k = r; k >= b[i]; k--) {
if (f[j][k] == f[j - a[i]][k - b[i]]+1) {
dp[j][k] = min(dp[j][k], dp[j - a[i]][k - b[i]] + c[i]);
}
else if(f[j][k] < f[j - a[i]][k - b[i]] + 1) {
f[j][k] = f[j - a[i]][k - b[i]] + 1;
dp[j][k] = dp[j - a[i]][k - b[i]] + c[i];
}
}
}
}
printf("%d\n", dp[m][r]);
return 0;
}