zoj 3634 Bounty hunter

题目链接:Bounty hunter


题目大意:

有一个人拥有X的钱,Y的能力,要从城市1走到n,在每个城市他可以选择花费 a[i]的钱提升1个单位的能力,也可以不提升。然后完成一个任务,可以获得 b[i]*当前能力的钱。

注意:可以花费实数单位的金钱,提升相应实数单位的能力,比如花费1.0,获得1.0/a[i]的能力。

问最终最多能够获得多少钱?

错解:

一个显然的想法就是我现在提升一个单位的能力的花费为 a[i],我的收益是 Σb[j] (j≥i)。只要后者大于前者就一定提升能力,那么收益一定是会变多的!

这个想法看起来很正确,收益不断的增加,但是有一个问题,加入我在i城市和i+1城市提升能力都会使收益增加,按照这个想法,一定先在 i提升,然后在 i+1提升。但是当 a[i]>>a[i+1]时,就是我在后者提升更划算,能够提升很多的能力,比都提升获得的能力值还要多。因为我在 i提升花掉了所有的钱,在 i+1的时候就没有太多的钱了。有了这个反例这个想法显然是错的。

正解:(我没想出来,想法来自别人)

关键点1:钱和攻击力没有关系。我的钱带来的收益和我的攻击力带来的收益可以分开考虑,似乎很合理!

关键点2:钱和收益成正比,能力和收益成正比。钱越多收益越多,能力越大收益越多!(应该能证明,但是我不会证!)

这样,我们可以用 atc[i]表示带着1的钱进入 i城市能获得的最大的收益,mny[i]表示带着1的能力进入城市 i能获得的最多的钱数

初始时:atc[n]=b[n],mny[n]=max(1.0,1.0/a[n]*b[n]);

转移:atc[i]=b[i]*mny[i+1]+atc[i+1];   mny[i]=max(mny[i+1],1.0/a[i]*atc[i]);

//#pragma comment(linker,"/STACK:102400000,102400000")
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<string>
#define ll long long
#define db double
#define PB push_back
#define lson k<<1
#define rson k<<1|1
using namespace std;

const int N = 100005;

db a[N],b[N];
db atc[N],mny[N];

int main()
{
#ifdef PKWV
    freopen("in.in","r",stdin);
#endif // PKWV
    int n;
    db x,y;
    while(scanf("%d%lf%lf",&n,&x,&y)+1)
    {
        for(int i=1;i<=n;i++) scanf("%lf%lf",&a[i],&b[i]);
        atc[n]=b[n],mny[n]=max(1.0,1.0/a[n]*b[n]);
        for(int i=n-1;i>0;i--)
        {
            atc[i]=b[i]*mny[i+1]+atc[i+1];
            mny[i]=max(mny[i+1],1.0/a[i]*atc[i]);
        }
        printf("%.2f\n",x*mny[1]+y*atc[1]);
    }
    return 0;
}


猜你喜欢

转载自blog.csdn.net/u014076176/article/details/46897093
ZOJ