[AHOI2014/JSOI2014/一本通1722]骑士游戏 题解 (spfa做dp)
题目描述
在游戏中,JYY一共有两种攻击方式,一种是普通攻击,一种是法术攻击。两种攻击方式都会消耗JYY一些体力。采用普通攻击进攻怪兽并不能把怪兽彻底杀死,怪兽的尸体可以变出其他一些新的怪兽,注意一个怪兽可能经过若干次普通攻击后变回一个或更多同样的怪兽;而采用法术攻击则可以彻底将一个怪兽杀死。
游戏世界中一共有N种不同的怪兽,分别由1到N编号,现在1号怪兽入侵村庄了,JYY想知道,最少花费多少体力值才能将所有村庄中的怪兽全部杀死呢?
输入
第一行包含一个整数N。
接下来N行,每行描述一个怪兽的信息;
其中第i行包含若干个整数,前三个整数为Si,Ki和Ri,表示对于i号怪兽,普通攻击需要消耗Si的体力,法术攻击需要消耗Ki的体力。同时i号怪兽死亡后会产生Ri个新的怪兽。表示一个新出现的怪兽编号。同一编号的怪兽可以出现多个。
输出
输出一行一个整数,表示最少花费的体力值。
输入样例
4
4 27 3 2 3 2
3 5 1 2
1 13 2 4 2
5 6 1 2
输出样例
26
提示
样例解释
首先用花费4点体力用普通攻击,然后出现的怪兽编号是2,2和3。再花费10点体力用法术攻击杀死两个编号为2的怪兽。剩下3号怪兽,花费1点体力用普通攻击。此时村庄里还有编号为2和4的怪兽。最后花费11点体力用法术攻击将这两只怪兽彻底杀死。一共花费的体力是\(4+5+5+1+5+6=26\)。
数据规模
\(2≤N≤2×10^5 ,1≤R_i,ΣR_i≤10^6 ,1≤K_i,S_i≤5×10^{14}\)
主要思路
定义\(f_i\)表示完全清除第i个怪兽的体力。
不难得出 \(f_i=min(k_i,s_i+\underset{j表示i怪兽死亡后产生的新怪兽}{Σf_j})\)
而这个生成的怪兽链可能形成个环,所以我们不能用传统DP的方法做。而要使用spfa跑这个\(f_i\)。
首先需要建一张图 \(G1\) ,\(i\)死后生成了\(j\)就可以连一条\(i->j\)的边
然后需要建一张反图,用来\(f_i\)更新时,让\(f_i\)的父节点入队更新。
更新条件是\(s_i+Σf_j<f_i\)。
不难看出\(f_i\)的不可能大于\(k_i\),所以可以用\(k_i\)为\(f_i\)初始化。
代码
#include <iostream>
#include <cstdio>
#include <queue>
using namespace std;
typedef long long ll;
const int N = 2e5 + 128;
const int M = 1e6 + 128;
struct ios//快读
{
inline char read()
{
static const int IN_LEN = 1 << 18 | 1;
static char buf[IN_LEN], *s, *t;
return (s == t) && (t = (s = buf) + fread(buf, 1, IN_LEN, stdin)), s == t ? -1 : *s++;
}
template <typename _Tp>
inline ios &operator>>(_Tp &x)
{
static char c11, boo;
for (c11 = read(), boo = 0; !isdigit(c11); c11 = read())
{
if (c11 == -1)
return *this;
boo |= c11 == '-';
}
for (x = 0; isdigit(c11); c11 = read())
x = x * 10 + (c11 ^ '0');
boo && (x = -x);
return *this;
}
} io;
namespace G1
{
int head[N], nxt[M], to[M];
int p = 0;
inline void add_edge(int f, int t)
{
to[++p] = t;
nxt[p] = head[f];
head[f] = p;
}
}
namespace G2 //反图
{
int head[N], nxt[M], to[M];
int p = 0;
inline void add_edge(int f, int t)
{
to[++p] = t;
nxt[p] = head[f];
head[f] = p;
}
}
ll s[N], k[N];
ll f[N];
bool vis[N];
int n;
ll spfa()
{
queue<int> Q;
for (int i = 1; i <= n; i++)
Q.push(i);
while (!Q.empty())
{
int k = Q.front();
Q.pop();
vis[k] = false;
ll sum = s[k];
for (int i = G1::head[k]; i != 0; i = G1::nxt[i])
sum += f[G1::to[i]];
if (sum < f[k])
{
f[k] = sum;
for (int i = G2::head[k]; i != 0; i = G2::nxt[i])//通知父节点
if (!vis[G2::to[i]])
Q.push(G2::to[i]), vis[G2::to[i]] = true;
;
}
}
return f[1];
}
int main()
{
io >> n;
for (int i = 1; i <= n; i++)
{
int r;
io >> s[i] >> k[i] >> r;
for (int j = 1; j <= r; j++)
{
int t;
io >> t;
G1::add_edge(i, t);
G2::add_edge(t, i);
}
f[i] = k[i];
}
printf("%lld", spfa());
return 0;
}
[AHOI2014/JSOI2014/一本通1722]骑士游戏 题解 (spfa做dp)的更多相关文章
- 2019.01.22 bzoj3875: [Ahoi2014&Jsoi2014]骑士游戏(spfa+dp)
传送门 题意简述:nnn个怪物,对于编号为iii的怪物可以选择用aia_iai代价将其分裂成另外的bib_ibi个怪物或者用cic_ici代价直接消灭它,现在问消灭编号为1的怪物用的最小代价. ...
- 「AHOI2014/JSOI2014」骑士游戏
「AHOI2014/JSOI2014」骑士游戏 传送门 考虑 \(\text{DP}\). 设 \(dp_i\) 表示灭种(雾)一只编号为 \(i\) 的怪物的代价. 那么转移显然是: \[dp_i ...
- 【BZOJ3875】[Ahoi2014&Jsoi2014]骑士游戏 SPFA优化DP
[BZOJ3875][Ahoi2014&Jsoi2014]骑士游戏 Description [故事背景] 长期的宅男生活中,JYY又挖掘出了一款RPG游戏.在这个游戏中JYY会扮演一个英勇的 ...
- BZOJ 3875: [Ahoi2014]骑士游戏 dp+spfa
题目链接: 题目 3875: [Ahoi2014]骑士游戏 Time Limit: 30 Sec Memory Limit: 256 MB 问题描述 [故事背景] 长期的宅男生活中,JYY又挖掘出了一 ...
- BZOJ 3875: [Ahoi2014]骑士游戏 spfa dp
3875: [Ahoi2014]骑士游戏 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=3875 Description [故事背景] 长 ...
- 【BZOJ3875】【AHOI2014】骑士游戏 [Spfa][DP]
骑士游戏 Time Limit: 30 Sec Memory Limit: 256 MB[Submit][Status][Discuss] Description 在这个游戏中,JYY一共有两种攻击 ...
- bzoj3875 【Ahoi2014】骑士游戏 spfa处理后效性动规
骑士游戏 [故事背景] 长期的宅男生活中,JYY又挖掘出了一款RPG游戏.在这个游戏中JYY会 扮演一个英勇的骑士,用他手中的长剑去杀死入侵村庄的怪兽. [问题描述] 在这个游戏中,JYY一共有两种攻 ...
- [bzoj3875] [Ahoi2014]骑士游戏
3875: [Ahoi2014]骑士游戏 Time Limit: 30 Sec Memory Limit: 256 MBSubmit: 844 Solved: 440[Submit][Status ...
- BZOJ 3875: [Ahoi2014]骑士游戏
d[i]表示消灭i所需的最小体力值, d[i] = min(S[i], K[i]+Σd[x]), Σd[x]表示普通攻击而产生的其他怪兽. 因为不是DAG, 所以用个队列类似SPFA来更新答案. -- ...
- bzoj 3875 骑士游戏 - spfa - 动态规划
Description [故事背景] 长期的宅男生活中,JYY又挖掘出了一款RPG游戏.在这个游戏中JYY会 扮演一个英勇的骑士,用他手中的长剑去杀死入侵村庄的怪兽. [问题描述] 在这个游戏中,J ...
随机推荐
- 逆向实战31——xhs—xs算法分析
前言 本文章中所有内容仅供学习交流,抓包内容.敏感网址.数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除! 公众号链接 目标网站 aH ...
- Android Compose开发
目录 好处 入门 Composable 布局 其他组件 列表 verticalScroll 延迟列表 内容内边距 性能 修饰符 偏移量 requiredSize 滚动 添加间距Spacer Butto ...
- SpringCloud组件:Feign之日志输出
目录 Feign之日志输出 Feign日志输出说明 前期准备 构建项目 tairan-spring-cloud-feign-logger配置 源码位置 Feign之日志输出 在我们日常开发过程中,经常 ...
- SQL之 数据库表字段约束与索引
第三范式 MySQL四种字段约束 主键约束 非空约束 唯一约束 创建索引 添加和删除索引
- 使用 PMML 实现模型融合及优化技巧
在机器学习的生产环境中,我们经常需要将多个模型的预测结果进行融合,以便提高预测的准确性.这个过程通常涉及到多个模型子分的简单逻辑回归融合.虽然离线训练时我们可以直接使用sklearn的逻辑回归进行训练 ...
- CodeGeeX vscode代码提示,智能问答
CodeGeeX 官网 https://codegeex.cn/zh-CN/ CodeGeeX vscode代码提示,智能问答
- br 词根 分支 broad bread branch brother broom 看到abroad后查到的
br-分支 cl-集合 pater-父亲 br/other 兄弟-br/oom笤帚-br/eed繁殖-br/ood一窝-br/eak打破-br/anch分枝 cl/ash碰撞-class/ify分类- ...
- j-link仿真器的作用和价值以及Ubuntu下使用注意事项
一 J-LINK是什么? J-Link是SEGGER公司为支持仿真ARM内核芯片推出的JTAG仿真器.配合IAR EWAR,ADS,KEIL,WINARM,RealView等集成开发环境支持所有A ...
- Android Swtich开关样式调整
原文:Android Swtich开关样式调整 - Stars-One的杂货小窝 接入百度人脸的demo时候,发现了内置的switch开关比较好看,看了下实现方法,原来只是改了下样式,记录一下 效果: ...
- linux下find命令根据系统时间查找文件用法
find 命令有几个用于根据您系统的时间戳搜索文件的选项.这些时间戳包括 mtime 文件内容上次修改时间 atime 文件被读取或访问的时间 ctime 文件状态变化时间 mtime 和 atime ...