多结果的背包问题,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;
}

posted @ 2023-06-25 16:54  Landnig_on_Mars  阅读(6)  评论(0编辑  收藏  举报  来源