A monster is attacking the Cyberland!
Master Yang, a braver, is going to beat the monster. Yang and the monster each have 3 attributes: hitpoints (HP), offensive power (ATK) and defensive power (DEF).
During the battle, every second the monster's HP decrease by max(0, ATKY - DEFM), while Yang's HP decreases bymax(0, ATKM - DEFY), where index Y denotes Master Yang and index M denotes monster. Both decreases happen simultaneously Once monster's HP ≤ 0 and the same time Master Yang's HP > 0, Master Yang wins.
Master Yang can buy attributes from the magic shop of Cyberland: h bitcoins per HP, a bitcoins per ATK, and d bitcoins per DEF.
Now Master Yang wants to know the minimum number of bitcoins he can spend in order to win.
The first line contains three integers HPY, ATKY, DEFY, separated by a space, denoting the initial HP, ATK and DEF of Master Yang.
The second line contains three integers HPM, ATKM, DEFM, separated by a space, denoting the HP, ATK and DEF of the monster.
The third line contains three integers h, a, d, separated by a space, denoting the price of 1 HP, 1 ATK and 1 DEF.
All numbers in input are integer and lie between 1 and 100 inclusively.
The only output line should contain an integer, denoting the minimum bitcoins Master Yang should spend in order to win.
1 2 1 1 100 1 1 100 100
99
100 100 100 1 1 1 1 1 1
0
For the first sample, prices for ATK and DEF are extremely high. Master Yang can buy 99 HP, then he can beat the monster with 1 HP left.
For the second sample, Master Yang is strong enough to beat the monster, so he doesn't need to buy anything.
题意:
奥特曼打小怪兽,各有血值,攻击力,防御力三个属性。每秒钟两个人同时掉血,分别为各自攻击力减去对方防御力。小怪兽攻击力比较强,但是奥特曼会开挂啊。去商店买属性,三个价钱还不一样,问怎样买能赢而且花钱最少。但是这道题要注意两个人是一起掉血,只要小怪兽被打死了,奥特曼剩一滴血也没事,但不能也挂了。
题解:
先找切入点,如果从加的属性来看的话三个属性,价钱不同,而且最优方案还是和具体情况相关,难度太大。换个切入点,我们可不可以二分找到最少的花钱数,从一个比较大的值开始不断二分,每次判断能不能打死,能打死继续分,打不死就是上一个。总能找到最小的花钱数。现在关键就是钱怎么花?价钱不一样,给谁感觉都不太合适,干脆就暴力一点,三个for循环,剪枝看能不能A得掉。设计成递减循环,有多少花多少一旦能干掉直接跳出,比从0开始慢慢加会快很多。
代码实现:
<span style="font-size:14px;">#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <cstring>
#define INF 0xffffff
using namespace std;
int y[3],m[3],p[3];//存的东西真多
int result;
bool solve(int);//解决函数
bool if_win(int,int,int);//传入三个属性加成,判断能不能成功打怪
int main()
{
double lb=0,ub=INF;
result=0xfffffff;
scanf("%d%d%d",&y[0],&y[1],&y[2]);
scanf("%d%d%d",&m[0],&m[1],&m[2]);
scanf("%d%d%d",&p[0],&p[1],&p[2]);
if(if_win(0,0,0))//先裸着打打看
{
printf("%d\n",0);
return 0;
}
//二分找最少的钱数
for(int i=0;i<100;i++)
{
int mid=(int)((lb+ub)/2+0.5);
if(solve(mid)) ub=mid;
else lb=mid;
if(lb==ub||ub-lb==1) break;
}
printf("%d\n",result);
return 0;
}
bool solve(int x)
{
int i;//血值
int j;//攻击力
int z;//防御力
for(i=x/p[0];i>=0;i--)
{
for(j=(x-i*p[0])/p[1];j>=0;j--)
{
//攻击力加了还没小怪兽防御力高就别打了,买装备去
if(y[1]+j<m[2])
break;
for(z=(x-i*p[0]-j*p[1])/p[2];z>=0;z--)
{
int prise=p[0]*i+p[1]*j+p[2]*z;
if(if_win(i,j,z))
{
result=min(result,prise);
return true;
}
}
}
}
return false;
}
bool if_win(int i,int j,int z)
{
//这种肯定不行
if(y[1]+j<=m[2])
return false;
//看看得打多少次
int time=m[0]/(y[1]+j-m[2]);
//要是不能刚好打死就再打一回合
if(m[0]%(y[1]+j-m[2])!=0)
time++;
//看看奥特曼还有血吗?
if(y[0]+i-time*(m[1]-y[2]-z)>0)
return true;
else
return false;
}</span>