P1149. 2023.03.30-第一题-塔子哥玩游戏(dp)
题目内容
塔子哥是一名拥有独特天赋的冒险者,他拥有一双敏锐的眼睛,能够寻找到别人无法察觉的宝石和宝藏。为了寻找更多的宝藏和宝石,他踏上了一段新的旅程。
在这段旅程中,他来到了一个神秘的游戏世界。这个游戏世界有 个关卡和 种宝石。每一个关卡都有一个boss或商店。当他打败一个boss时,他可以获得一个新的宝石。但是,由于他只能携带一个宝石,他必须丢掉当前的宝石才能取走新的宝石。此外,当他到达一个商店时,商店会收购一种特定的宝石,并给他一些钱。
塔子哥想知道自己最多可以获得多少钱。因此,他开始了他的游戏之旅,希望能在这个游戏世界中获得尽可能多的财富。
输入描述
输入第一行为两个整数 和 ,()
接下来 行,每一行第一个输入为一个字符,如果字符为 b,则代表boss,后面输入一个整数,代表宝石种类。
如果字符为 m ,则代表商店,后面输入两个整数,代表该商店收取的宝石种类和价格。
输出描述
输出塔子哥最多可以获得多少钱。
样例
输入
5 3
b 3
b 1
m 3 50
b 2
m 1 100
输出
100
很显然宝石只有被出售之后才会获得实际的收益,所以对各个掉落的宝石,可以进行一个抽象的多线程dp
通俗点来说就是,假设没有只允许携带一个宝石这个条件。但是在商店只能卖出一个指定宝石
那么问题就很显然了,以每一次遇到商店作为一个分割,计算每次只卖出一个宝石的最大收益
虽然这种最优解的形式有点贪心那味道,但是第一个样例就指明了这不是贪心,而是动态规划
定义 dp[i] 为第1~i个关卡被探索后选择宝石能达到的最大值
那么可以定义状态转移方程,如果遇到当前位置为boss关,那么记录此时有那个宝石;
如果遇到商店,则出售唯一允许出售的宝石(等价于选择了这个宝石并带到了商店),或者不出售宝石(等价于之前没有拿这个宝石)。
定义f[i]为第i关时能获得的最多的钱,用哈希表与前缀和优化状态转移
如果遇到当前位置为boss关,那么记录此时有那个宝石,f[i]=f[i-1]
如果遇到商店,则出售唯一允许出售的宝石 使用哈希表找到最近一次获得该宝石的位置j
f[i]=max(f[i-1],f[type]+value)
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=1e6+100;
int dp[maxn];
int pre[maxn];
int main(){
int n,m;
cin>>n>>m;
memset(pre,-1,sizeof(pre));
for(int i=1;i<=n;i++){
dp[i]=dp[i-1];
char c;
int type,price;
cin>>c;
if(c=='m'){
cin>>type>>price;
// 对应不交易宝石和交易宝石两种可能的情况
if(pre[type]!=-1) dp[i]=max(dp[i],pre[type]+price);//交易或者不交易
}
else{
cin>>type;
// 当前打败了boss,获得宝石的选择权
// 这样写可以联系第一个样例来看,遇到商店一定出售的做法不一定最优,可以有如下选择
// (1)选择不出售宝石,也就是当前没有拿可以出售的那种宝石,选择从上一次没有交易此宝石的价值转移
// (2)选择出售宝石,也就是将这个宝石带上,到商店再看,可能卖,可能不卖
pre[type]=max(pre[type],dp[i]);
}
}
printf("%d\n",dp[n]);
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现