您的位置:首页 > 其它

ZOJ 3634 Bounty hunter(DP)

2013-07-24 09:19 357 查看
题目链接:Click here~~

题意:

一个人带着初始的 X 元钱和 Y 的攻击力,依次经过 n 个城市从 1~n。在每个城市可以做两件事,花钱提升攻击力和用攻击力赚钱,且顺序不能改变。

问最后从 n 出来时最多能有多少钱。(提升攻击力单价为 1点 / a[i] 元,但可以提升非整点的攻击力;攻击力赚钱情况为 b[i] 元 / 点)

解题思路:

由于攻击力和钱数都可能是实数,所以不能以它两个作为状态了。

问题中赚钱只有一个途径——打工。而打工没有什么限制,即有多少攻击力,就能赚多少相应的钱。不会因为当前的钱多或攻击力多,而获得额外的钱。

同样地,提升攻击力也不会因为钱多或攻击力多,而获得额外的攻击力。

这点对问题有什么帮助呢?

1、在某个城市 i,1点攻击力能获得的最大钱数 和 1块钱能获得的最大钱数 与 当前拥有的钱数和攻击力 是无关的。

2、钱和攻击力能获得的最大钱数可以分开考虑。

令 att_m[i] 表示带着 1点攻击力 进入城市 i 能获得的最大钱数,mon_m[i] 表示带着 1块钱 进入城市 i 能获得的最大钱数。

初始值:att_m
= b
, mon_m
= max(1,1.0/a
* b
)。

转移方程: att_m[i] = mon_m[i+1] * b[i] + att_m[i+1] ,mon_m[i] = max(mon_m[i+1],1.0/a[i] * (b[i] * mon_m[i+1] + att_m[i+1]))。

#include <stdio.h>
#include <string.h>
#include <algorithm>

using namespace std;

const int N = 1e5 + 5;

double a
,b
,mon_m
,att_m
;

int main()
{
    int n,X,Y;
    while(~scanf("%d%d%d",&n,&X,&Y))
    {
        for(int i=1;i<=n;i++)
            scanf("%lf%lf",&a[i],&b[i]);
        att_m
 = b
;
        mon_m
 = max(1.0,1.0/a
 * b
);
        for(int i=n-1;i>=1;i--)
        {
            att_m[i] = mon_m[i+1] * b[i] + att_m[i+1];
            mon_m[i] = max(mon_m[i+1],1.0/a[i] * (b[i] * mon_m[i+1] + att_m[i+1]));
        }
        printf("%.2f\n",X*mon_m[1] + Y*att_m[1]);
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: