题意:wzc有n份面粉,有m种糕点可以制作。每种糕点的制作除了面粉之外还需要对应的馅料(每种糕点与其馅料是一一对应的)。对于第i种糕点,目前剩余的对应馅料还有ai份,制作一份糕点需要bi份馅料和ci份面粉,可以销售处di元钱。当然他也可以选择不加馅料直接卖,利用c0的面粉制作出一份糕点,可以售出d0元钱。

分析:多重背包,我们可以把c0的面粉当作另一种物品,当循环前面的糕点时,就可以正确地计算出答案。我们定义\(f[i][j]:\)前i种糕点,j个体积的最大收益,我们的\(DP转移方程式:f[i][j] = max(f[i][j], f[i - 1][j - k * b[i]] + k * d[i]),并且k * b[i] <= a[i]且k * c[i] <= j\)。我们把剩下的不加馅料的面粉也计算进来,就可以求出整个最大收益了。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>

using namespace std;
const int N = 1005;

struct Node
{
	int a, b, c, d;
}p[N];

int f[15][1500];

int main()
{
	int n, m, c0, d0;
	scanf("%d%d%d%d", &n, &m, &c0, &d0);

	for (int i = 1; i <= m; ++i) scanf("%d%d%d%d", &p[i].a, &p[i].b, &p[i].c, &p[i].d);

	for(int i = 1; i <= m; ++i)
		for (int j = 1; j <= n; ++j)
		{
			for (int k = 0; k * p[i].b <= p[i].a && k * p[i].c <= j; ++k)
			{
				f[i][j] = max(f[i][j], f[i - 1][j - k * p[i].c] + k * p[i].d);
			}
		}

	for (int j = 1; j <= n; ++j)
	{
		for (int k = 0; k * c0 <= j; ++k)
		{
			f[m + 1][j] = max(f[m + 1][j], f[m][j - k * c0] + k * d0);
		}
	}

	printf("%d\n", f[m + 1][n]);
	

	return 0;
}