DP

Problem - E - Codeforces

题意

有个 BOSS 有 \(H\;(1<=H<=5000)\) 血量,\(s\) 点防御

有两种武器可用攻击 BOSS,伤害分别为 \(p_1,p_2\;(s<min(p_1,p_2)<=5000)\), 冷却时间分别为 \(t_1,t_2\;(1<=t_1,t_2<=10^{12})\)

每一时刻如果 cd 好了可以选择攻击,造成 \(p_i-s\) 点伤害;如果两个武器一起攻击可以造成 \(p_1+p_2-s\) 点伤害

0 时刻两个武器都刚进入 cd,求将 BOSS 消灭的最短时间

思路

  1. 可以选择攻击的时刻一定是 \(p_1\) 或 \(p_2\) 的倍数,并且每次至少造成 1 点伤害,因此最多有 \(H\) 个需要抉择的时刻 \(T_i\)
  2. 当某时刻两个武器同时发射时,之后的操作就成了一个子问题
  3. 可以设 \(f[h]\) 为两个武器都刚进入 cd,打掉 h 血的最短时间,枚举 \(T_i\), 作为第一次刻意等待令两个武器同时发射的时刻,求出前 \(T_i\) 时间正常操作(即 cd 好了就放)造成的伤害 \(tot\), \(f[h]=min(f[h],f[h-tot]+T_i)\)

代码

#include <bits/stdc++.h>
using namespace std;
#define endl "\n" typedef long long ll;
typedef pair<int, int> PII; const int N = 5e3 + 10;
int p[3], H, s;
ll t[3], cnt[3];
ll f[N];
vector<ll> vt;
ll lcm(__int128 a, __int128 b)
{
__int128 t = a / __gcd(a, b) * b;
if (t >= (__int128)2e18)
t = 2e18;
return t;
} void presolve()
{
if (t[1] > t[2])
{
swap(t[1], t[2]);
swap(p[1], p[2]);
}
p[0] = p[1] + p[2] - s;
p[1] -= s, p[2] -= s;
t[0] = lcm(t[1], t[2]);
for (int i = 1; i * p[1] <= H; i++)
vt.push_back(i * t[1]);
for (int i = 1; i * p[2] <= H; i++)
vt.push_back(i * t[2]);
sort(vt.begin(), vt.end());
vt.erase(unique(vt.begin(), vt.end()), vt.end());
} void solve()
{
memset(f, 0x3f, sizeof f);
f[0] = 0;
for (int h = 1; h <= p[1]; h++)
f[h] = t[1];
for (int h = p[1] + 1; h <= H; h++)
{
for (auto T : vt)
{
if (T % t[0] == 0)
{
cnt[0] = T / t[0];
cnt[1] = T / t[1] - cnt[0];
cnt[2] = T / t[2] - cnt[0];
}
else if (T % t[1] == 0)
{
if (T < t[2])
{
cnt[1] = T / t[1];
cnt[2] = cnt[0] = 0;
}
else
{
cnt[1] = T / t[1];
cnt[2] = T / t[2];
ll TT = (cnt[2] - 1) * t[2];
cnt[0] = TT / t[0] + 1;
cnt[1] -= cnt[0], cnt[2] -= cnt[0];
}
}
else
{
cnt[2] = T / t[2];
cnt[1] = T / t[1];
ll TT = (cnt[1] - 1) * t[1];
cnt[0] = TT / t[0] + 1;
cnt[1] -= cnt[0], cnt[2] -= cnt[0];
}
ll tot = 0;
for (int i = 0; i < 3; i++)
tot += cnt[i] * p[i];
ll now = 0;
if (tot >= h)
now = T;
else
now = T + f[h - tot];
f[h] = min(f[h], now);
}
}
} int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> p[1] >> t[1] >> p[2] >> t[2] >> H >> s;
presolve();
solve();
ll ans = f[H];
cout << ans << endl;
return 0;
}

最新文章

  1. 0041 Java学习笔记-多线程-线程池、ForkJoinPool、ThreadLocal
  2. .net 执行sql包含go语句的处理
  3. 网页实时聊天之js和jQuery实现ajax长轮询
  4. webform:分页组合查询
  5. c++ IO的继承结构
  6. MagSpoof:能预测并窃取你下一张信用卡号码的廉价设备
  7. Ubuntu 启动黑屏解决
  8. 给windows的VM更换网卡到VMNET3从E1000
  9. 【Shell脚本学习11】Shell注释
  10. 转载:简化IT程序员工作生活的4个窍门
  11. matlab读取指定路径下的图像
  12. BZOJ 1876: [SDOI2009]SuperGCD( 更相减损 + 高精度 )
  13. Moq &amp; RhinoMocks
  14. .net core 杂记:日记记录
  15. CentOS7 升级 gvim 到 8.x 版本
  16. Pytorch学习笔记(二)---- 神经网络搭建
  17. ZOJ 2588 Burning Bridges 割边(处理重边)
  18. element-ui &lt;el-date-picker&gt; 回显格式 yyyy-MM-dd 传值格式 yyyyMMddHHmmss
  19. Unity跳转场景进度条制作教程(异步加载)
  20. iOS 提交应用过程出现的错误及#解决方案#images can't contain alpha channels or transparencies

热门文章

  1. XSS漏洞利用案例实验
  2. 新款 c++ web framework 支持orm http/2
  3. buuctf_Dest0g3_crypto
  4. Win10的OneDrive目录在旧系统里无法访问、删不掉
  5. Array list练习
  6. python导入xls数据到db--优化版
  7. USACO 2023 January Contest, Bronze Problem 3. Moo Operations
  8. ChatGPT:好家伙,每个人内心的一块魔镜
  9. 在执行npm install执行报错node-sass
  10. python判断密码连续,重复,大小写、数字、符号混合密码复杂度要求