背包DP

背包DP(部分)

例:F - Piggy-Bank

完全背包问题,区别是求的是最小值,所以只需要初始化为最大值,max改成min即可

代码示例:

//#pragma comment(linker,   "/STACK:10240000000000,10240000000000")
//#pragma GCC optimize(2)

#include <bits/stdc++.h>

#define For(i,a,b) for (int i=(a);i<=(b);++i)
#define Fod(i,b,a) for (int i=(b);i>=(a);--i)
#define mls multiset
#define lb lower_bound
#define ub upper_bound
#define pb push_back
#define pob pop_back
#define itt iterator
#define lowbit(x) x & (-x)
#define clr(x) memset(x, 0, sizeof(x));

typedef long long ll;
typedef unsigned long long ull;
		
using namespace std;
const int MAXN = 0x7fffffff;
const int MOD = 1000000007;
int f[10005];
int w[505];
int c[505];
int main ()
{	
	ios::sync_with_stdio(false);
	cin.tie(0);
	int t;
	cin >> t;
	while(t--)
	{
		int e, ful;
		cin >> e >> ful;
		int n;
		int spa = ful - e;
		cin >> n;
		For(i, 1, n)
			cin >> w[i] >> c[i];

		memset(f, 0x3f, sizeof f);
		f[0] = 0;
			
		For(i, 1, n)
		{
			For(v, c[i], spa)
					f[v] = min(f[v], f[v - c[i]] + w[i]);
		}

		if(f[spa] != 0x3f3f3f3f)
			printf("The minimum amount of money in the piggy-bank is %d.\n", f[spa]);
		else printf("This is impossible.\n");

	}


	return 0;
}	
/*
f[i][v] 表示把前i种物品放进v容量的背包里能产生的最小价值
*/

关于完全背包 f只用了一维,并且第二层循环是c[i] - spa的解释:

我们知道多重背包问题可以由01背包转化而来,也就是每个物品多了个取k个的操作

第一种优化,我们可以把无限数量的单个物品,用\(2^k\)表示,也就是把\(2^k\)个第i个物品看成一个物品

最终优化,在01背包中,我们内层循环的v是从spa开始然后到0的,如此是为了在进行状态方程转移时,我们保证对于考虑是否放第i个物品的状态是从一个绝对没有这件单品的子状态转移而来,因为每个物品只能放一个,但在多重背包中则没有这种顾虑,所以可以从0 - spa进行循环,如此一来可以节省一重的循环,是时间复杂度压缩到O(VN),V为背包最大容量,N为物品个数

混合三种背包问题:

只需要在内层循环判断是01背包还是完全背包、多重背包即可

参考:dd大牛的《背包九讲》 - 贺佐安 - 博客园 (cnblogs.com)

上一篇:Vue路由


下一篇:“如果没有Ta”系列报道之一 告别要体面,请好好说“再见”