【题解】p1964 【mc生存】卖东西

dalao写的多重背包好深奥啊qwq,蒟蒻来弱弱地发一波题解
算法:多重背包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <bits/stdc++.h>
using namespace std;
struct data{
int w;
int v;
int c;
string s;
}a[105] , b[134405];//a是原数组,b是用来处理的数组(具体看下面)
int n , m , t = 0 , x = 21 , f[22];
int main()
{
cin >> m >> n;//输入
x -= m;//除去不能卖的东西剩下的格子
for(int i = 1; i <= n; i++)
{
cin >> a[i].w >> a[i].v >> a[i].c >> a[i].s;//输入
for(int j = 1; j < i; j++)//如果前面有过同样的就合并
{
if(a[j].s == a[i].s)
{
a[j].w += a[i].w;//合并
a[i].w = -1;//标记
}
}
}
for(int i = 1; i <= n; i++)
{
if(a[i].w != -1)//合并到前面的就不考虑
{
int p;
bool bo = false;
if (a[i].w % a[i].c > 0)//每放满一个格子,就算一个物件,占用一个空间,从而达到转01背包的作用
{
p = a[i].w / a[i].c + 1;
bo = 1;//标记,最后一个没放满
}
else
p = a[i].w / a[i].c;
for(int j = 1; j <= p; j++)//计算价值 {
if(bo == 1 && j == p)
{
b[++t].v = a[i].v * (a[i].w % a[i].c);//如果最后一个没放满,要特判
b[t].w = 1;//算占用一个空间
}
else
{
b[++t].v = a[i].v * a[i].c;
b[t].w = 1;
}
}
}
}
for(int i = 1; i <= t; i++)
for(int j = x; j >= b[i].w; j--)
f[j] = max(f[j] , f[j - b[i].w] + b[i].v);//华丽的01背包模板
cout << f[x];//输出
}