Description

对于多数RPG游戏来说,除了剧情就是打怪升级。本题的任务是用最短的时间取得所有战斗的胜利。这些战斗必须按照特定的顺序进行,每打赢一场,都可能会获得一些补药,用来提升力量。本题只有两种补药:“加1药”和“乘2药”,分别让你的力量值加1和乘以2。

战斗时间取决于你的力量。每场战斗可以用6个参数描述:p1, p2, t1, t2, w1, w2。如果你的力量小于p1,你将输掉战斗;如果你的力量大于p2,需要t2秒赢得战斗;如果力量位于p1和p2(包括p1和p2),战斗时间从t1线性递减到t2。比如p1=50,p2=75,t1=40,t2=15,你的力量为55,则战斗获胜需要35秒。注意,战斗时间可能不是整数。最后两个参数w1和w2分别表示战斗胜利后获得的“加1药”和“乘2药”的数量。注意,你不一定要立刻使用这些补药,可以在需要的时候再用,但不能在战斗中使用补药。

按顺序给出每场战斗的参数,输出赢得所有战斗所需的最短总时间。战斗必须按顺序进行,且不能跳过任何一场战斗。

Input

输入最多包含25组测试数据。每组数据第一行为两个整数n和p(1<=n<=1000, 1<=p<=100),即战斗的场数和你的初始力量值。以下n行每行6个整数p1, p2, t1, t2, w1, w2(1<=p1

Output

对于每组数据,输出最短总时间(单位:秒),保留两位小数。如果无解,输出“Impossible”(不含引号)。

Sample Input

1 55

50 75 40 15 10 0

2 55

50 75 40 15 10 0

50 75 40 15 10 0

3 1

1 2 2 1 0 5

1 2 2 1 1 0

1 100 100 1 0 0

1 7

4 15 35 23 0 0

1 1

2 3 2 1 0 0

0 0

Sample Output

35.00

60.00

41.00

31.73

Impossible

题目分析

读完这个题目,我们首先应该想到的是,这两瓶药水应该怎么用。

我们都知道:当力量越大的时候,“乘2药”的作用就越大,比如:力量为1,用了“乘2药”后,力量增加到了2;力量为2,用了“乘2药”,力量就增加到了4。因此,我们需要用搜索遍历的方法来计算最终用时,按照“乘2药”使用的瓶数来遍历。因此我们要讨论的问题是:战斗结束,你是否使用“乘2药”,用的话,你会用几瓶。

大致需要注意哪些:首先我们要知道搜索什么时候结束;力量值不能战斗胜利怎么办,力量值已经超过了此次战斗最大的力量值我们怎么处理。这3个问题弄明白之后,基本上就能解决了。

“加1药”只要有就用掉,它越早用越好,没必要留到后面用。

以上就是题目的粗略分析,不是很清楚的话,可以看代码,自认为注释非常详细了。

代码

// 1262ms

import java.util.Scanner;

public class Main {

// 关卡类,记录每场战斗的信息

private class Combat {

// 前面6个是输入的数据,即战斗的信息

// gapP = p2 - p1后面计算用的比较频繁,直接算出来比较好

// gapT = t1- t2同上

int p1, p2, t1, t2, w1, w2, gapP, gapT;

}

private Combat[] combat;// 记录所有战斗的信息,下标从0开始

private Scanner sc;

private int n, p;// 战斗场数,初始战力值

private double totalTime;// 所有战斗胜利用时,即最终结果

// battle()方法中要用到

private int newPower;// 新力量值

private int newBottles;// 新药水数量

private double newUsedTime;// 新用时

// 当前力量值与最低力量值的差,同最大力量差的比值,用于计算当前战斗用时

private double scale;

public Main() {

sc = new Scanner(System.in);

int i;

// 申请堆空间

combat = new Combat[1001];

for(i = 0; i < 1001; i++) {

combat[i] = new Combat();

}

while(input()) {

totalTime = Double.MAX_VALUE;// 赋最大值

battle(0, p, 0, 0);// 初始胜利0场,力量值p,药水0瓶,用时0秒

if(totalTime == Double.MAX_VALUE) {

System.out.println("Impossible");

} else {

System.out.printf("%.2f", totalTime);

System.out.println();

}

}

sc.close();

}

/**

* @return 是否结束输入

*/

private boolean input() {

n = sc.nextInt();

p = sc.nextInt();

if(0 == n) {

return false;

}

int i;

for(i = 0; i < n; i++) {

combat[i].p1 = sc.nextInt();

combat[i].p2 = sc.nextInt();

combat[i].t1 = sc.nextInt();

combat[i].t2 = sc.nextInt();

combat[i].w1 = sc.nextInt();

combat[i].w2 = sc.nextInt();

// 计算差值

combat[i].gapP = combat[i].p2 - combat[i].p1;

combat[i].gapT = combat[i].t1 - combat[i].t2;

}

return true;

}

/**

* @param wons已经胜利战斗数量

* @param power上一次战斗结束时候的力量值

* @param bottles目前“乘2药”的瓶数

* @param usedTime胜利wons场战斗用的时间

*/

private void battle(int wons, int power, int bottles, double usedTime) {

// 如果已经用的时间超过了目前的最短时间

// 后面的战斗也就没必要了,直接退出

if(usedTime > totalTime) {

return;

}

// 所有战斗都胜利了

if(wons == n) {

// 如果用时比目前最短时间还少的话

if(usedTime < totalTime) {

totalTime = usedTime;// 更新最短时间记录

}

return;// 退出

}

int i;

// 这是最后一场战斗,战斗前将药水用完,不用就浪费了

if(wons == n - 1) {

for(i = 0; i < bottles; i++) {

power *= 2;

}

bottles = 0;

}

// 循环考虑怎么处理剩余的药水

for(i = 0; i <= bottles; i++) {

if(i > 0) {

// i等于0的时候,表示不用药水,不能乘2;其他情况,每次用1瓶

power *= 2;

}

// 力量值不低于当前战斗要求的最低力量值,才能继续战斗;否则循环,继续用药水

if(power >= combat[wons].p1) {

// 力量值不低于要求最高力量值

if(power >= combat[wons].p2) {

// 力量值已经超过了最大值100

if(power >= 100) {

// 后面的所有战斗,将会以最快速度结束

for(i = wons; i < n; i++){

usedTime += combat[i].t2;

}

battle(n, power, 0, usedTime);

break;

}

// 当前战斗胜利,将“加1药”全部用完

newPower = power + combat[wons].w1;

// 原来有bottles瓶,用了i瓶,当前战斗胜利,获得了w2瓶

newBottles = bottles - i + combat[wons].w2;

newUsedTime = usedTime + combat[wons].t2;

battle(wons + 1, newPower, newBottles, newUsedTime);

break;// 这个break很关键,没有的话会超时,亲测...

} else {// 力量值低于最高力量值

newPower = power + combat[wons].w1;

newBottles = bottles - i + combat[wons].w2;

// 下面3行,计算当前战斗用时

scale = (power - combat[wons].p1) * 1.0 / combat[wons].gapP;

newUsedTime = usedTime;

newUsedTime += combat[wons].t1 - scale * combat[wons].gapT;

battle(wons + 1, newPower, newBottles, newUsedTime);

}

}

}

}

public static void main(String[] args) {

new Main();

}

}

代码补充

可能大家在Java里面数组内存比较喜欢——用多少,就申请多少这种做法(反正我是这样的),但是这个题目,由于搜索开销较大,我们应该从开销方面来考虑如何写代码。题目指明可能有1000场战斗,也就是数组要1000大小,这么大的申请堆空间的时间开销还是很大的。我提交的相差了大约500ms,很可怕。所以此题应该直接一次性申请堆空间1001大小。

代码中有几个地方用到了break,这里主要是为了除去不必要的遍历,以节约时间。这种做法也就是我们通常说的剪枝,自认为剪的还不够好。如果大家通过阅读代码之后想到了更好的方法(也就是提交时间更短),或者还有疑问的话,欢迎评论以及留言(邮箱在友情链接),我会及时回复。

小结

这个题目并没有我们想象的难,主要是注意一些细节问题。这道题目还检查出了我的关于内部类知识的漏洞,申请类对象数组需要两次new,否则知识申请了一个数组,并没有实例。有这个疑问的可参考我自己写的与此对应的博客给内部类对象数组属性赋值时报错:Exception in thread “main” java.lang.NullPointerException。

java打怪升级代码_1255: 打怪升级(Java)相关推荐

  1. 怎么运行java虚拟机_Java代码如何运行在Java虚拟机中

    我们都知道要运行Java代码就必须要有JRE,也就是Java运行时环境,JRE中包含了Java程序的必需组件,包括Java虚拟机以及Java核心类库,然而运行C++代码则不需要额外的运行时环境,只需要 ...

  2. java调用子系统代码_深入理解JAVA虚拟机-Idea远程执行本地Java代码 - Java 技术驿站-Java 技术驿站...

    今天在看深入理解JAVA虚拟机的9.3节,作者实现了一个远程执行功能.这个功能可以在远程服务器中临时执行一段程序代码,而去不依赖jdk版本,不改变原有服务端程序的部署,不依赖任何第三方库,不入侵原有的 ...

  3. 数据结构java 图实验代码_20172329 2018-2019 《Java软件结构与数据结构》实验三报告...

    20172329 2018-2019-2 <Java软件结构与数据结构>实验三报告 课程:<Java软件结构与数据结构>html 班级: 1723java 姓名: 王文彬lin ...

  4. java猜拳游戏代码_猜拳游戏 - java代码库 - 云代码

    [java]代码库public class Computer { String name; int score; public int showfist(){ int quan; quan=(int) ...

  5. java界面设计 代码_Android开发——纯JAVA代码方式界面设计

    之前我们写Android页面都是在XML文件里写的,今天我们换个口味,在JAVA文件里写我们的Android页面.至于为什么要用java来写,不直接在XML文件里写,这个问题的答案很简单,因为麻烦嘛, ...

  6. java冒泡排序经典代码_15道经典Java算法题(含代码) 建议收藏

    [程序1] 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少?//这是一个菲波拉契数列问题 publi ...

  7. java语言生日蛋糕代码_AcWing 168. 【Java】生日蛋糕

    // 1. dfs 顺序: 枚举可能的 r,h 拼成一层蛋糕 (顺序是层内操作) // 2. dfs 状态: preR, preH, 当前层,累计体积,累计面经 (状态是分支和给下次的依赖值) // ...

  8. java点歌系统代码_ktv 一个用java写的ktv点歌系统,用ACCESS数据库 Develop 238万源代码下载- www.pudn.com...

    文件名称: ktv下载 收藏√  [ 5  4  3  2  1 ] 开发工具: Java 文件大小: 25661 KB 上传时间: 2014-04-10 下载次数: 1 提 供 者: 成俊杰 详细说 ...

  9. java员工管理系统代码_员工管理系统JAVA源码(源码大小8M)

    员工管理系统JAVA源码(源码大小8M) 本站提供几百套大型商业源码,平均一元一套,火爆下载中...... QQ:283072.283672 EMAIL:web@hur.cn.jhwjeffrey@1 ...

最新文章

  1. PyTorch 安装和基本运算— Tensor 的数据类型(浮点型、整型、随机浮点型等)、基本运算(绝对值、求和、裁剪、求商、求积、求幂等)、Tensor 与 Numpy 转换
  2. 10 Java程序员面试宝典视频课程之Servlet
  3. dedecms 后台添加新字段
  4. 决策树 随机森林 xgboost_一文搞定XGboost 面试常见问题
  5. python面向对象编程的优点-Python语言有哪些优点?
  6. linux pyside2 安装包,Qt for Python 5.12发布下载,附PySide2和Shiboken2介绍
  7. 前端每日值得花时间看的博客
  8. 为给全球提供互联网服务 这家公司决定发射3236颗卫星
  9. OpenShift 4 之 Image Registry、Image 和 ImageStream 概念和相关操作
  10. 没有密码怎样删除officescan
  11. HCNA每日一练错误
  12. Python-数据分析-常用检验-2-相关系数检验
  13. html css做椭圆,简单实例:用css3画椭圆
  14. java开发手册 - 码出规范 - 要点整理
  15. 手机是如何做到精准定位的
  16. Centos 6 yum安装出错
  17. 测试war包(免费)
  18. scrum立会报告+燃尽图(第二周第七次)
  19. satoken+ gateway网关统一鉴权 初版
  20. Android界面布局练习

热门文章

  1. 深入理解Java虚拟机-高效并发
  2. [言论]熊十力谈读书(摘录于《非常道——1840-1999的中国话语》)
  3. python电路仿真_蔡氏电路仿真实验
  4. ​建行数据从Teradata迁移到Greenplum大揭秘
  5. 学会计为什么要学计算机基础,会计实操为什么要学习手工做账?
  6. 2022大学生就业指导答案——雷五明、雷辉等
  7. 吸附去除溶液重金属离子工艺原理
  8. Re: 酷似抓虾的ruby on rail网站-猫爪
  9. 神经网络-非线性激活ReLU
  10. Elasticsearch在thinkphp5中的使用增删改查(模糊查询、批量查询)