# 装饰珠 **题目描述** 在怪物猎人这一款游戏中,玩家可以通过给装备镶嵌不同的装饰珠来获取 相应的技能,以提升自己的战斗能力。 已知猎人身上一共有 6 件装备,每件装备可能有若干个装饰孔,每个装饰孔有各自的等级,可以镶嵌一颗小于等于自身等级的装饰珠 (也可以选择不镶嵌)。 装饰珠有 M 种,编号 1 至 M,分别对应 M 种技能,第 i 种装饰珠的等级为 $L_i$,只能镶嵌在等级大于等于 $L_i$ 的装饰孔中。 对第 i 种技能来说,当装备相应技能的装饰珠数量达到 $K_i$个时,会产生$W_i$($K_i$)的价值,镶嵌同类技能的数量越多,产生的价值越大,即$W_i$($K_{i-1}$)<$W_i$($K_i$)。但每个技能都有上限$P_i$(1≤$P_i$≤7),当装备的珠子数量超过$P_i$时,只会产生$W_i$($P_i$)的价值。 对于给定的装备和装饰珠数据,求解如何镶嵌装饰珠,使得 6 件装备能得到的总价值达到最大。 **输入描述** 输入的第 1 至 6 行,包含 6 件装备的描述。其中第i行的第一个整数Ni表示第i件装备的装饰孔数量。后面紧接着Ni个整数,分别表示该装备上每个装饰孔的等级L(1≤ L ≤4)。 第 7 行包含一个正整数 M,表示装饰珠 (技能) 种类数量。 第 8 至 M + 7 行,每行描述一种装饰珠 (技能) 的情况。每行的前两个整数$L_j$(1≤ $L_j$ ≤4)和$P_j$(1≤ $P_j$ ≤7)分别表示第 j 种装饰珠的等级和上限。接下来$P_j$个整数,其中第 k 个数表示装备该中装饰珠数量为 k 时的价值$W_j$(k)。 其中$1 ≤ N_i ≤ 50,1 ≤ M ≤ 10^4,1 ≤ W_j(k) ≤ 10^4。$ **输出描述** 输出一行包含一个整数,表示能够得到的最大价值。 **输入** ``` 1 1 2 1 2 1 1 2 2 2 1 1 1 3 3 1 5 1 2 3 5 8 2 4 2 4 8 15 3 2 5 10 ``` **输出** ``` 20 ``` **样例说明** 按照如下方式镶嵌珠子得到最大价值 20,括号内表示镶嵌的装饰珠的种类编号: ``` 1: (1) 2: (1) (2) 3: (1) 4: (2) (2) 5: (1) 6: (2) ``` 4 颗技能 1 装饰珠,4 颗技能 2 装饰珠 $W_1(4) + W_2(4) = 5 + 15 = 20。W_1(4)+W_2(4)=5+15=20$。 以下错误的一项是? ## aop ### before ```cpp #include using namespace std; ``` ### after ```cpp ``` ## 答案 ```cpp 其他三个都不对 ``` ## 选项 ### A ```cpp int main() { vector Hole(5); int N, tmp, total = 0; for (int i = 0; i < 6; ++i) { cin >> N; for (int j = 0; j < N; ++j) { cin >> tmp; ++Hole[tmp]; ++total; } } cin >> N; vector L(N + 1); vector> W(N + 1, vector()); for (int i = 1; i <= N; ++i) { cin >> L[i]; cin >> tmp; W[i].resize(tmp + 1); for (int j = 1; j <= tmp; ++j) { cin >> W[i][j]; } } vector> dp(N + 1, vector(total + 1)); int sum = 0; int kind = 0; for (int level = 4; level >= 1; --level) { sum += Hole[level]; if (sum == 0) continue; for (int k = 1; k <= N; ++k) { if (L[k] == level) { ++kind; for (int i = 1; i <= sum; ++i) { dp[kind][i] = dp[kind - 1][i]; } for (int i = 1; i < W[k].size(); ++i) { for (int j = sum; j >= i; --j) { dp[kind][j] = max(dp[kind][j], dp[kind - 1][j - i] + W[k][i]); } } } } } cout << *max_element(dp[kind].begin(), dp[kind].end()) << endl; return 0; } ``` ### B ```cpp int Solution() { int n, sum = 0, L[5] = {0}, m, M, W[5][10] = {0}, le, P, res = 0; for (int i = 0; i < 6; i++) { cin >> n; sum += n; for (int j = 0; j < n; j++) { cin >> m; L[m]++; } } cin >> M; int ww; for (int i = 0; i < M; i++) { cin >> le >> P; for (int j = 1; j <= P; j++) { cin >> ww; if (ww > W[le][j]) W[le][j] = ww; if ((j + 1 > P) && P < 7) for (int k = j + 1; k <= 7; k++) W[le][k] = W[le][k - 1]; } } for (int i = 0; i <= L[4]; i++) { for (int j = 0; j <= (sum - L[1] - L[2] - i); j++) { for (int k = 0; k <= (sum - L[1] - (i + j)); k++) { for (int s = 0; s <= (sum - (i + j + k)); s++) { int a, b, c, d; if (i > 7) a = 7; else a = i; if (j > 7) b = 7; else b = j; if (k > 7) c = 7; else c = k; if (s > 7) d = 7; else d = s; res = max(res, W[4][a] + W[3][b] + W[2][c] + W[1][d]); } } } } return res; } int main() { cout << Solution(); return 0; } ``` ### C ```cpp constexpr size_t MAXN = 55, MAXS = 305, MAXM = 1e4 + 5; int n[MAXN], cnt[5], Lv[MAXM], p[MAXM], w[MAXM][MAXN]; int dp[MAXM][MAXS]; int m; inline void Read() { ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); for (int i = 1; i <= 6; i++) { cin >> n[i]; for (int j = 1, x; j <= n[i]; j++) { cin >> x; cnt[x]++; } } cin >> m; for (int i = 1; i <= m; i++) { cin >> Lv[i] >> p[i]; for (int j = 1; j <= p[i]; j++) cin >> w[i][j]; } } inline int DP() { memset(dp, 0x80, sizeof dp), dp[0][0] = 0; int ans = 0, sum = 0, tot = 0; for (int L = 4; L >= 1; L--) { sum += cnt[L]; for (int i = 1; i <= m; i++) if (Lv[i] == L) { tot++; for (int k = 0; k <= sum; k++) dp[tot][k] = dp[tot - 1][k]; for (int j = 1; j <= p[i]; j++) for (int k = j; k <= sum; k++) dp[tot][k] = max(dp[tot][k], dp[tot - 1][k - j] + w[i][j]); } } for (int i = 0; i <= sum; i++) ans = max(ans, dp[tot][i]); return ans; } signed main() { Read(); cout << DP(); } ```