【HDU5931 2016CCPC东北地区大学生程序设计竞赛 - 重现赛 J】【线性规划 乱搞】Mission Possible 购买护甲和回复力和速度使得最小成本穿越D距离

48 篇文章 0 订阅
2 篇文章 0 订阅

Mission Possible

Time Limit: 36000/18000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 100    Accepted Submission(s): 16


Problem Description
Mr. Frog loves playing video games. However, it seems that he does not have enough gift in this field, so he often gets stuck in some certain levels. Now this annoying situation comes to him again.

In this mission, Mr. Frog is asked to pass a
dangerous region which is currently under his enemies, control. Every second he is inside this region, his enemies would attack him with everything they have. Luckily, he is wearing a powersuit and still have time to enhance it.

powersuit has three main attributes: health point, velocity and recover speed. In the begin¬ning of this mission, the powersuit has H health points, and is able to move at no faster than Vm/s. Once the health point of powersuit is less than 0, the powersuit would be totally destroyed and Mr. Frog would immediately be killed. At the end of every second that the powersuit still works, the suit would repair itself and recover R health points.

After precise calculation, Mr. Frog has found that, to go through this area, he needs to run at least D meters distance, and every second his enemies, attack would cause A health point loss. Note that attacks take place all the time while the recover   only happens at the end of every second, so you can consider that, in   every whole second, the powersuit first loses A health points and then recovers R health points at the end of it, if it still works at that moment.

Mr. Frog could enhance his powersuit at any time he wants during the mission. At the beginning all three attributes of his powersuit equals to 0. He needs to pay   G1 in order to increase H by 1, while   G2  to increase V by 1 and   G3  to increase R by 1. For any of these three values, he can only increase it by non-negative integer. For some well-known reasons, Mr. Frog does not want to finish the game too quickly, so you   cannot  increase the powersuit's speed to   more than  D m/s. Since you looks so clever, now Mr. Frog wants to know not only how he can finish this mission, but also the way to spend the least money, can you help him?
 

Input
The first line contains only one integer T, which indicates the number of test cases. For each test case,there are five integers   D,A,G1,G2,G3 .
 

Output
For each test case,output one line “Case #x: Ans’’,where x is the case number (starting from 1) and Ans is the minimum cost required to finish the mission.
 

Sample Input
  
  
2 5 1 1 2 5 10 1 1 2 5
 

Sample Output
  
  
Case #1: 7 Case #2: 8
Hint
1 <= D,A <= 500000, 1 <= G1, G2, G3 <= 200
 

Source


#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<ctype.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); }
#define MS(x,y) memset(x,y,sizeof(x))
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b>a)a = b; }
template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b<a)a = b; }
const int N = 0, M = 0, Z = 1e9 + 7, inf = 0x3f3f3f3f;
template <class T1, class T2>inline void gadd(T1 &a, T2 b) { a = (a + b) % Z; }
int casenum, casei;
LL D, A, GH, GV, GR;
LL check(int V)
{
	double T = 1.0 * D / V;
	int RECT = T - 0.0001;
	LL ret = 1e18;
	{
		LL R = 0;
		LL H = max(T * A - RECT * R, (double)A) + 0.9999;
		gmin(ret, H * GH + R * GR);
	}
	{
		LL R = A;
		LL H = max(T * A - RECT * R, (double)A) + 0.9999;
		gmin(ret, H * GH + R * GR);
	}
	return ret;
}
int main()
{
	scanf("%d", &casenum);
	for (casei = 1; casei <= casenum; ++casei)
	{
		scanf("%lld%lld%lld%lld%lld", &D, &A, &GH, &GV, &GR);
		LL ans = 1e18;
		for (int l = 1; l <= D; ++l)
		{
			LL cost = check(l) + l * GV;
			gmin(ans, cost);
		}
		printf("Case #%d: %lld\n", casei, ans);
	}
	return 0;
}
/*
【trick&&吐槽】
1,本题不满足三分性质,三分失败
2,attacks take place all the time while the recover only happens at the end of every second
	所以我们要用double

3,其实只要考虑两种策略即可AC——
	1,全部靠护甲不要恢复
	2,全部靠恢复只要最基础的护甲

【题意】
我们一个人要穿过距离D,其每秒会受到A的攻击,这个攻击是每秒均摊的,也就是以浮点数的时刻计算
初始有
1,生命值H=0
2,速度V=0
3,每秒结束后的恢复力R=0

我们可以提升H,V,R,花费金钱数分别为GH,GV,GR,使得数值+1,V值的提升程度不能超过D
问你,如何花费,可以使得我们花费最小的金钱通过D的距离

D和A的范围都是[1,5e5]
GH,GV,GR的范围都是[1,200]

【类型】
线性规划 贪心 暴力

【分析】
首先,我们可以考虑枚举V∈[1,D],然后得到T(T为double类型)

这时可以考虑再枚举R
我们有RECT*R+H>=T*A,所以可以贪心得到最小的H
然后用GV*V+GH*H+GR*R更新答案即可。
只不过这里的的复杂度有些大
我们考虑不枚举R,而是贪心发现H=T*A-RECT*R
我们希望(T*A-RECT*R)*GH + GR*R尽可能小
即要使得T*A*GH + GR*R - RECT*GH*R尽可能小
即要使得(T*A*GH)+(GR-RECT*GH)*R尽可能小

GR-RECT*GH是可能为正可以为负的,所以R在其最小取值或最大取值时最优。
但是有一点要注意,我们需要时刻维护使得T*A-RECT*R >= H
但是这并不影响我们的决策点

【时间复杂度&&优化】
O(D)

*/


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值