【模拟 贪心】B4207 [常州市赛 2021] 战士|普及+

B4207 [常州市赛 2021] 战士

题目背景

搬运自 http://czoj.com.cn/p/443。数据为民间数据。

题目描述

X \text X X 在玩一款操控战士和怪物战斗的游戏。战士初始生命值为 iH \text{iH} iH 、初始攻击力为 iA \text{iA} iA 。怪物只有一个,初始生命值为 H H H
战斗是回合制的,且有一个回合数限制 M M M 。如果在 M M M 回合内怪物还没有被杀死,小 X \text X X 就失败了。在每个回合,战士先行动,怪物再行动。
每当战士行动,小 X \text X X 可以命令战士做以下两件事中的一件:

  • 攻击,让怪物的生命值减少当前战士攻击力的数值。
  • 磨刀,让战士攻击力增加 dA \text{dA} dA

每当怪物行动,怪物会攻击战士,使战士的生命值减少 C i C_i Ci ,其中 i i i 为回合数。
当一个角色生命值小于等于 0 0 0 时,角色会死亡。

  • 如果怪物死亡,那么战斗就结束了。
  • 如果战士死亡,会立刻复活,将生命值和攻击力恢复为初始数值。

现在小 X X X 想问问你,最少能在几个回合内杀死怪物。

输入格式

第一行, 5 5 5 个整数,分别为 iH,iA , H , dA , M \text{iH,iA},H,\text{dA},M iH,iA,H,dA,M,意义见问题描述。
第二行 M M M 个整数,表示第 i i i 个回合怪物的攻击力 C i C_i Ci

输出格式

输出一行一个整数表示最少能在几个回合内杀死怪物。如果 M M M 回合内杀不死,输出 -1

输入输出样例 #1

输入 #1

4 1 6 1 8
2 1 1 1 1 1 1 1

输出 #1

5

说明/提示

样例解释

其中一种合法方案:

  • 第一回合:战士磨刀,战士攻击力变为 2 2 2 ;怪物攻击,战士生命值变成 2 2 2
  • 第二回合:战士攻击,怪物生命值变为 4 4 4 ;怪物攻击,战士生命值变成 1 1 1
  • 第三回合:战士攻击,怪物生命值变为 2 2 2 ;怪物攻击,战士死亡后复活,生命值变为 4 4 4 ,攻击力变为 1 1 1
  • 第四回合:战士攻击,怪物生命值变为 1 1 1 ;怪物攻击,战士生命值变成 3 3 3
  • 第五回合:战士攻击,怪物死亡。

数据范围

本题共有 10 10 10 个测试点。
对于所有数据, 1 ≤ iH,iA , H ≤ 10 9 , 0 ≤ dA ≤ 10 9 , 1 ≤ C i ≤ M ≤ 2 × 10 5 1\le \text{iH,iA},H\le10^9,0\le \text{dA}\le10^9,1\le C_i\le M\le2\times10^5 1iH,iA,H109,0dA109,1CiM2×105

测试点编号 M M M特殊性质
1 1 1 ≤ 2 × 10 5 \le 2\times10^5 2×105 dA = 0 \text{dA}=0 dA=0
2 ∼ 3 2\sim3 23 ≤ 20 \le20 20
4 ∼ 5 4\sim5 45 ≤ 30 \le30 30
6 ∼ 8 6\sim8 68 ≤ 10 3 \le10^3 103
9 ∼ 10 9\sim10 910 ≤ 2 × 10 5 \le2\times10^5 2×105

模拟 贪心

a[i]表示,不轮回的情况下,战士i回合操作的最大伤害。long long 型,如果大于LLONG_MAX/4,取LLONG_MAX/4。
dead=0,第dead回合轮回。hurt=0LL,记录轮回前的伤害。HP=iH记录战士剩余生命值。
枚举i = 1 to M
{ if(hurt + a[i-dead] >= H){return i ;}
if(C[i] >= HP){ HP=iH;dead=i;hurt += a[i-dead];}
else HP -= C[i]。}
return -1
计算a[i]
令磨刀x回合,显然先磨刀再攻击。总伤害,用a代替iA,d代替da:
( a + d × x ) ( i − x ) = a × i + ( i × d − a ) x − d × x × x 式子一 \Large(a+d \times x)(i-x)=a\times i + (i\times d -a)x - d \times x\times x 式子一 (a+d×x)(ix)=a×i+(i×da)xd×x×x式子一
x 2 − 2 x i × d − a 2 d x^2-2x\frac{i\times d- a}{2d} x22x2di×da
float f = i × d − a d × 2.0 , 式子一 = − d ( x − f ) 2 + 某个常数 \large f =\large \frac{i\times d -a }{d \times 2.0},式子一=-d(x-f)^2 + 某个常数 f=d×2.0i×da,式子一=d(xf)2+某个常数 如果f是整数,x取f时最大值。
如果f不是整数,向下取整或向上取整时是最大值。枚举两种情况。
注意 x 1 = ⌊ f ⌋ , x 2 = ⌈ f ⌉ x1 = \lfloor \ f \rfloor,x2 = \lceil \ f \rceil x1= f,x2= f 如果x1(x2) > i,取i。小于0,取0。
用3个样例,过不了。暴力枚举x,错误的样例能过,但超时。
说明:F函数正确,x的极值错误。
自己构造了N组数据,没发现错误。晚上睡觉前,灵光一现:a和d相差很大的时候是否有问题?
31号早上,一试果然如此? a = = 3 , d = = 1 a==3,d==1 a==3,d==1 暴力算法和计算的x不一致。

a[i] = max(F(x1, i), F(x2, i));auto tmp = F(0, i);for (int j = 1; j < i; j++) {tmp = max(tmp, F(j, i));}//Assert::AreEqual(tmp, a[i]);assert(tmp== a[i]);;

i为1时,暴力计算的是3,解方程的是4。
最终发现错误原因:赋值号打成了等号。

if (x1 >= i) { x1 == i; }

代码

核心代码

#include <iostream>
#include <sstream>
#include <vector>
#include<map>
#include<unordered_map>
#include<set>
#include<unordered_set>
#include<string>
#include<algorithm>
#include<functional>
#include<queue>
#include <stack>
#include<iomanip>
#include<numeric>
#include <math.h>
#include <climits>
#include<assert.h>
#include<cstring>
#include<list>
#include<array>#include <bitset>
using namespace std;template<class T1, class T2>
std::istream& operator >> (std::istream& in, pair<T1, T2>& pr) {in >> pr.first >> pr.second;return in;
}template<class T1, class T2, class T3 >
std::istream& operator >> (std::istream& in, tuple<T1, T2, T3>& t) {in >> get<0>(t) >> get<1>(t) >> get<2>(t);return in;
}template<class T1, class T2, class T3, class T4 >
std::istream& operator >> (std::istream& in, tuple<T1, T2, T3, T4>& t) {in >> get<0>(t) >> get<1>(t) >> get<2>(t) >> get<3>(t);return in;
}template<class T1, class T2, class T3, class T4, class T5, class T6, class T7 >
std::istream& operator >> (std::istream& in, tuple<T1, T2, T3, T4,T5,T6,T7>& t) {in >> get<0>(t) >> get<1>(t) >> get<2>(t) >> get<3>(t) >> get<4>(t) >> get<5>(t) >> get<6>(t);return in;
}template<class T = int>
vector<T> Read() {int n;cin >> n;vector<T> ret(n);for (int i = 0; i < n; i++) {cin >> ret[i];}return ret;
}
template<class T = int>
vector<T> ReadNotNum() {vector<T> ret;T tmp;while (cin >> tmp) {ret.emplace_back(tmp);if ('\n' == cin.get()) { break; }}return ret;
}template<class T = int>
vector<T> Read(int n) {vector<T> ret(n);for (int i = 0; i < n; i++) {cin >> ret[i];}return ret;
}template<int N = 1'000'000>
class COutBuff
{
public:COutBuff() {m_p = puffer;}template<class T>void write(T x) {int num[28], sp = 0;if (x < 0)*m_p++ = '-', x = -x;if (!x)*m_p++ = 48;while (x)num[++sp] = x % 10, x /= 10;while (sp)*m_p++ = num[sp--] + 48;AuotToFile();}void writestr(const char* sz) {strcpy(m_p, sz);m_p += strlen(sz);AuotToFile();}inline void write(char ch){*m_p++ = ch;AuotToFile();}inline void ToFile() {fwrite(puffer, 1, m_p - puffer, stdout);m_p = puffer;}~COutBuff() {ToFile();}
private:inline void AuotToFile() {if (m_p - puffer > N - 100) {ToFile();}}char  puffer[N], * m_p;
};template<int N = 1'000'000>
class CInBuff
{
public:inline CInBuff() {}inline CInBuff<N>& operator>>(char& ch) {FileToBuf();while (('\r' == *S) || ('\n' == *S) || (' ' == *S)) { S++; }//忽略空格和回车ch = *S++;return *this;}inline CInBuff<N>& operator>>(int& val) {FileToBuf();int x(0), f(0);while (!isdigit(*S))f |= (*S++ == '-');while (isdigit(*S))x = (x << 1) + (x << 3) + (*S++ ^ 48);val = f ? -x : x; S++;//忽略空格换行		return *this;}inline CInBuff& operator>>(long long& val) {FileToBuf();long long x(0); int f(0);while (!isdigit(*S))f |= (*S++ == '-');while (isdigit(*S))x = (x << 1) + (x << 3) + (*S++ ^ 48);val = f ? -x : x; S++;//忽略空格换行return *this;}template<class T1, class T2>inline CInBuff& operator>>(pair<T1, T2>& val) {*this >> val.first >> val.second;return *this;}template<class T1, class T2, class T3>inline CInBuff& operator>>(tuple<T1, T2, T3>& val) {*this >> get<0>(val) >> get<1>(val) >> get<2>(val);return *this;}template<class T1, class T2, class T3, class T4>inline CInBuff& operator>>(tuple<T1, T2, T3, T4>& val) {*this >> get<0>(val) >> get<1>(val) >> get<2>(val) >> get<3>(val);return *this;}template<class T = int>inline CInBuff& operator>>(vector<T>& val) {int n;*this >> n;val.resize(n);for (int i = 0; i < n; i++) {*this >> val[i];}return *this;}template<class T = int>vector<T> Read(int n) {vector<T> ret(n);for (int i = 0; i < n; i++) {*this >> ret[i];}return ret;}template<class T = int>vector<T> Read() {vector<T> ret;*this >> ret;return ret;}
private:inline void FileToBuf() {const int canRead = m_iWritePos - (S - buffer);if (canRead >= 100) { return; }if (m_bFinish) { return; }for (int i = 0; i < canRead; i++){buffer[i] = S[i];//memcpy出错			}m_iWritePos = canRead;buffer[m_iWritePos] = 0;S = buffer;int readCnt = fread(buffer + m_iWritePos, 1, N - m_iWritePos, stdin);if (readCnt <= 0) { m_bFinish = true; return; }m_iWritePos += readCnt;buffer[m_iWritePos] = 0;S = buffer;}int m_iWritePos = 0; bool m_bFinish = false;char buffer[N + 10], * S = buffer;
};
class Solution {public:int Ans(int iH, int iA, const int H, int dA, vector<int>& C){				const int M = C.size();vector<long long> a(M + 1);auto F = [&](long long x,long long i) {const long long ll1 = dA * x + iA;const long long ll2 = i - x;if (LLONG_MAX / ll1 < ll2) { return (long long) H; }return ll1 *ll2 ;};for (long long i = 1; i <= M; i++) {if (0 == dA) {a[i] = iA * i;continue;}const long long f1 = i * dA - iA;const long long f2 = dA * 2LL;long long x1 = f1 / f2;					long long x2 = x1 + (0 != f1 % f2);if (x1 >= i) { x1 = i; }if (x2 >= i) { x2 = i; }if (x1 < 0) { x1 = 0; }if (x2 < 0) { x2 = 0; }a[i] = max(F(x1, i), F(x2, i));					}int dead = 0;long long hurt = 0, HP = iH;	for (int m = 1; m <= M; m++) {if (hurt + a[m - dead] >= H) { return m; }if (C[m-1] >= HP) {HP = iH; hurt += a[m - dead]; dead = m;  }else { HP -= C[m-1]; }}return -1;}};int main() {
#ifdef _DEBUGfreopen("a.in", "r", stdin);
#endif // DEBUG	ios::sync_with_stdio(0); cin.tie(nullptr);//CInBuff<> in; COutBuff<10'000'000> ob;	int iH,iA,H,dA,Q;cin>> iH >> iA >> H >> dA >> Q;auto C = Read<int>(Q);
#ifdef _DEBUG	printf("iH=%d,iA=%d,H=%d,dA=%d",iH,iA,H,dA);Out(C, ",C=");//Out(edge, ",edge=");		/*Out(que, ",que=");*///Out(ab, ",ab=");//Out(par, "par=");//Out(que, "que=");//Out(B, "B=");
#endif // DEBUG	auto res = Solution().Ans(iH, iA, H, dA, C);cout << res;return 0;
};

单元测试

	int iH, iA,  H,  dA;vector<int> C;TEST_METHOD(TestMethod01){iH = 4, iA = 1, H =1, dA = 0, C = { 2,1,1,1,1,1,1,1 };auto res = Solution().Ans(iH, iA, H, dA, C);AssertEx(1, res);}TEST_METHOD(TestMethod11){iH = 4, iA = 1, H = 6, dA = 1, C = { 2,1,1,1,1,1,1,1 };auto res = Solution().Ans(iH, iA, H, dA, C);AssertEx(5, res);}TEST_METHOD(TestMethod12){iH = 4, iA = 3, H = 4, dA =1 , C.assign(100'000,1);auto res = Solution().Ans(iH, iA, H, dA, C);AssertEx(2, res);}

# 扩展阅读

我想对大家说的话
工作中遇到的问题,可以按类别查阅鄙人的算法文章,请点击《算法与数据汇总》。
学习算法:按章节学习《喜缺全书算法册》,大量的题目和测试用例,打包下载。重视操作
有效学习:明确的目标 及时的反馈 拉伸区(难度合适) 专注
闻缺陷则喜(喜缺)是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛
失败+反思=成功 成功+反思=成功

视频课程

先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771
如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176

测试环境

操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/bicheng/85032.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

37-Oracle 23 ai Shrink Tablespace(一键收缩表空间)

小伙伴们有没有经历过&#xff0c;超大表和超大数据的导入后&#xff0c;数据被删除了&#xff0c;然而空间迟迟不释放&#xff0c;存储添置又跟不上&#xff0c;业务空间告警的时候。收缩就很必须了&#xff0c;然而收缩需谨慎&#xff0c;数据大过天。DBMS_SPACE.SHRINK_TABL…

我自己动手写了一个MySQL自动化备份脚本,基于docker

MySQL自动化备份Docker方案 该方案仅需通过 Docker Compose 就能轻松完成部署。你可以自由配置数据库连接信息&#xff0c;无论是远程数据库&#xff0c;还是本地数据库&#xff0c;都能实现无缝对接。在备份频率设置上&#xff0c;支持按固定秒数间隔执行备份任务&#xff0c…

leetcode23-合并K个升序链表

leetcode 23 思路 遍历所有链表收集节点&#xff1a;将每个链表的节点断开其 next 指针后存入数组对数组进行排序&#xff1a;使用 JavaScript 的内置 sort 方法对节点数组按值排序重新连接排序后的节点&#xff1a;遍历排序后的数组&#xff0c;依次连接每个节点形成新链表…

(十六)GRU 与 LSTM 的门控奥秘:长期依赖捕捉中的遗忘 - 更新机制对比

1 长期依赖捕捉能力的核心差异 1.1 信息传递路径&#xff1a;细胞状态 vs 单一隐藏状态 LSTM的“信息高速公路”机制 LSTM通过独立的细胞状态&#xff08;Cell State&#xff09; 传递长期信息&#xff0c;该状态可视为“直接通路”&#xff0c;允许信息跨越多个时间步而不被中…

HTTP 请求报文 方法

在 HTTP 请求报文 中&#xff0c;方法&#xff08;Method&#xff09; 是用来说明客户端希望对服务器资源执行的操作。它出现在 HTTP 报文的第一行&#xff0c;称为 请求行&#xff0c;格式如下&#xff1a; METHOD Request-URI HTTP-Version例如&#xff1a; GET /index.h…

【深度解析】Java高级并发模式与实践:从ThreadLocal到无锁编程,全面避坑指南!

&#x1f50d; 一、ThreadLocal&#xff1a;线程隔离的利器与内存泄露陷阱 底层原理揭秘&#xff1a; 每个线程内部维护ThreadLocalMap&#xff0c;Key为弱引用的ThreadLocal对象&#xff0c;Value为存储的值。这种设计导致了经典内存泄露场景&#xff1a; // 典型应用&#…

使用存储型 XSS 窃取 cookie 并发送到你控制的服务器

&#x1f9ea; 第一步&#xff1a;准备监听服务接收 cookie 在你的本机&#xff08;非容器&#xff09;或 DVWA 所在主机运行以下 Python 监听代码&#xff0c;用于接收窃取的 cookie&#xff1a; 启动 HTTP 接收服务 # 在本机终端运行&#xff0c;监听 8081 端口&#xff0…

WebDebugX和多工具组合的移动端调试流程构建:一个混合App项目的实践案例

前段时间参与了一个跨平台的医疗服务 App 项目&#xff0c;整体架构采用 Flutter 封装原生模块&#xff0c;部分功能模块嵌套 WebView 加载 H5 页面。开发过程中我们频繁遇到 Web 页面在移动端表现异常的问题&#xff0c;比如样式错乱、请求失败、性能延迟等&#xff0c;而这些…

图形编辑器基于Paper.js教程29:基于图层的所有矢量图元的填充规则实现

背景 在lightburn中&#xff0c;对于填充图层&#xff0c;有这样一个隐藏的逻辑&#xff0c;那就是&#xff0c;在加工时&#xff0c;填充规则是以填充图层的所有元素进行计算的&#xff0c;什么意思那&#xff1f; 如果你在填充图层中画了两个图形&#xff0c;一个圆&#xf…

Python 函数实战指南:提升编程效率的实用技巧

在 Python 编程的世界里&#xff0c;函数是构建高效代码的基石。掌握实用的函数技巧不仅能让代码更加简洁优雅&#xff0c;还能显著提升开发效率。我们一起将结合实际案例&#xff0c;深入剖析 Python 函数的使用技巧&#xff0c;帮助开发者在日常开发中事半功倍。 一、基础函数…

OPenCV CUDA模块图形变换----构建透视变换映射表函数buildWarpPerspectiveMaps()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 该函数用于构建一个透视变换&#xff08;Perspective Transform&#xff09;的映射表&#xff08;xmap / ymap&#xff09;&#xff0c;可用于后…

tcping工具使用指南

tcping是一个用于测试TCP端口连通性的工具&#xff0c;它类似于传统的ping命令&#xff0c;但工作在传输层(TCP)而不是网络层(ICMP)。 基本功能 tcping的主要功能包括&#xff1a; 测试目标主机特定TCP端口是否开放 测量TCP连接建立时间 统计丢包率和响应时间 安装方法 …

CSP 2024 入门级第一轮(88.5)

4. 以下哪个序列对应数字 00 至 88 的 44 位二进制格雷码&#xff08;Gray code&#xff09;&#xff1f;&#xff08; &#xff09; A. 0000, 0001, 0011, 0010, 0110, 0111, 0101, 1000 B. 0000, 0001, 0011, 0010, 0110, 0111, 0100, 0101 C. 0000, 0001, 0011, 0010, …

三菱FX-5U系列入门到精通

第2章 中间继电器 继电器工作模式:线圈得电,常开触点闭合,常闭触点断开。总结:中间继电器线圈电压分为:24VDC 110VAC 220VAC 380VAC PLC控制柜中常用的是24VDC比较多,而动力电柜中或者控制风机水泵的电柜中220VAC比较多。大部分选择24VDC,然后用触点控制220或者380,说白…

简历模板1——王明 | 高级数据挖掘工程师 | 5年经验

王明 | 高级数据挖掘工程师 | 5年经验 &#x1f4f1; (86) 189-xxxx-xxxx | &#x1f4e7; wangmingemail.com | &#x1f4cd; 深圳市 &#x1f4bb; GitHub | &#x1f454; LinkedIn &#x1f4bc; 工作经历 ​科技前沿集团 | 高级数据挖掘工程师 &#x1f4c5; 2021.06 …

【JVM】- 内存模式

Java内存模型&#xff1a;JMM&#xff08;Java Memory Model&#xff09;&#xff0c;定义了一套在多线程环境下&#xff0c;读写共享数据&#xff08;成员变量、数组&#xff09;时&#xff0c;对数据的可见性&#xff0c;有序性和原子性的规则和保障。 原子性 问题分析 【问…

AQS独占模式——资源获取和释放源码分析

AQS资源获取&#xff08;独占模式&#xff09; Node节点类 static final class Node {//标记当前节点的线程在共享模式下等待。static final Node SHARED new Node();//标记当前节点的线程在独占模式下等待。static final Node EXCLUSIVE null;//waitStatus的值&#xff0c…

压测过程中TPS上不去可能是什么原因

进行性能分析 接口没有报错或者错误率低于1%&#xff0c;继续增加并发还是一样&#xff0c;这个时候需要考虑几点 1.是否触发限流&#xff0c;比如waf、Nginx等情况&#xff0c;有没有一些限流的情况&#xff0c;如果触发了限流&#xff0c;请求是没有达到后端的&#xff0c;所…

Golang 解大整数乘法

文章目录 Golang 解大整数乘法问题描述&#xff1a;LeetCode 43. 字符串相乘思路Golang 代码 Golang 解大整数乘法 在初学 C 语言的时候&#xff0c;我们一定接触过“字符串相加”或“字符串相乘”之类的问题&#xff0c;对于初学者而言&#xff0c;这类问题的难度一般来说是比…

web3-区块链的技术安全/经济安全以及去杠杆螺旋(经济稳定)

web3-区块链的技术安全/经济安全以及去杠杆螺旋&#xff08;经济稳定&#xff09; 三个基本设计问题 技术安全 在技术结构中对其进行原子级的、瞬时利用&#xff08;无风险&#xff09; 无风险&#xff0c;因为攻击者的结果还是二进制的&#xff1a; 只会是攻击成功 获利或…