HELLO WORLD--一起加油(🍺)!|

kingwzun

园龄:3年6个月粉丝:111关注:0

2023-03-20 22:08阅读: 52评论: 0推荐: 0

装饰珠

image
在怪物猎人这一款游戏中,玩家可以通过给装备镶嵌不同的装饰珠来获取 相应的技能,以提升自己的战斗能力。

已知猎人身上一共有 6 件装备,每件装备可能有若干个装饰孔,每个装饰孔有各自的等级,可以镶嵌一颗小于等于自身等级的装饰珠 也可以选择不镶嵌。

装饰珠有 M 种,编号 1 至 M,分别对应 M 种技能,第 i 种装饰珠的等级为 Li,只能镶嵌在等级大于等于 Li 的装饰孔中。
对第 i 种技能来说,当装备相应技能的装饰珠数量达到 Ki个时,会产生WiKi的价值,镶嵌同类技能的数量越多,产生的价值越大,即WiKi1<WiKi

  • 但每个技能都有上限Pi1Pi7
  • 当装备的珠子数量超过Pi时,只会产生WiPi的价值。

对于给定的装备和装饰珠数据,求解如何镶嵌装饰珠,使得 6 件装备能得到的总价值达到最大。

来源: 圆宝の博客
文章作者: 郭梦圆
文章链接: https://ybao.xyz/2021/04/22/蓝桥杯真题——装饰珠/
本文章著作权归作者所有,任何形式的转载都请注明出处。

思路

这道题的题面较为复杂,但理清以后会发现,装备数其实没什么用, 实质是把各种各样的珠子放进不同等级的孔里(珠子等级≤孔等级)。

  • 同时每种珠子放进若干个会产生一个递增的价值,用一个数组描述;放多少个有上限,比如上限为5,则放进6个和5个的价值相同。

这道题和背包问题很像,但有两点不同

  • 第一点是高等级的珠子不能放进低等级的孔中,放入有限制;
    因此选择从高等级到低等级逐层开放孔数,同时优先放同等级的珠子,放入时就不会受到限制

  • 第二点是同种珠子放入不同的个数的价值是用一个数组描述的,而不是每个珠子是一样的价值。
    因此还需要遍历一下放入不同个数的情况。

这样即可转换为背包问题,孔数即相当于容量。

dp[i][j]表示前 i 种珠子放入 j 个孔中所能产生的最大价值。(这里前 i 个不是按照原来顺序的)

每开放一个等级就枚举与之等级相同的珠子放多少个,然后与前i1种珠子相对应转移过来的情况进行比较。

//必须先平行转移,因为有好几种转移情况(放i个)
for (int k = 0; k <= len; k++)
f[tot][k] = f[tot - 1][k];
//放i个该种珠子
for (int k = 1; k <= p[j]; k++)
for (int o = k ; o <= len; o++)
f[tot][o] = max(f[tot][o], f[tot - 1][o - k] + vec2[j][k - 1]);

代码

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e4 + 10;
int n;
int x[5];
int l[N], p[N];
vector<int> vec2[N];
int f[N][305];
signed main()
{
int n = 0;//总孔数
for (int i = 0; i < 6; i++){
int k;cin >> k;
n += k;
for (int j = 0; j < k; j++){
int t;cin >> t;
x[t]++;
}
}
int m;
cin >> m;
for (int i = 1; i <= m; i++){
cin >> l[i] >> p[i];
for (int j = 0; j < p[i]; j++){
int t;
cin >> t;
vec2[i].push_back(t);
}
}
int len = 0, tot = 0;
for (int i = 4; i >= 1; i--){
len += x[i];// 逐步开放
for (int j = 1; j <= m; j++){
if (l[j] != i) continue;
tot++;
//必须先平行转移,因为有好几种转移情况(放i个)
for (int k = 0; k <= len; k++)
f[tot][k] = f[tot - 1][k];
//放i个该种珠子
for (int k = 1; k <= p[j]; k++)
for (int o = k ; o <= len; o++)
f[tot][o] = max(f[tot][o], f[tot - 1][o - k] + vec2[j][k - 1]);
}
}
int ans = 0;
for (int i = 0; i <= len; i++) ans = max(ans, f[tot][i]);
cout << ans << endl;
return 0;
}

本文作者:kingwzun

本文链接:https://www.cnblogs.com/kingwz/p/17238116.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   kingwzun  阅读(52)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起