UVA 12294 RPG battles (DP)

In many typical RPG games, you battle with bad guys, creatures, monsters or ghosts etc. all the time.

After each battle, you may get magic potions that power you up, so you’ll get stronger and stronger,
and finally defeat the big boss. In this problem, we only consider two kinds of potion: stronger and
double power. If you drink a bottle of stronger potion, your power increases by 1; if you drink a bottle
of double power potion, your power doubles.
How long each battle lasts depends on how powerful you are. Each battle is described by six
parameters: p1, p2, t1, t2, w1, w2. That means, if your power is less than p1, you will be defeated; if
your power is greater than p2, you’ll need t2 seconds to defeat all the enemies. If your power is between
p1 and p2 (inclusive), the time needed for the battle decreases linearly from t1 to t2. For example, if
p1 = 50, p2 = 75, t1 = 40, t2 = 15, and your power is 55, then the battle lasts for 35 seconds. Note that
the time needed for battles may be non-integers. The last two parameters, w1 and w2, represent the
number of bottles of stronger potion and double power potion you got after winning the battle. Note
that you don’t have to drink these potions immediately. You can drink them later if that’ll decrease
the total time. You cannot drink potions during a battle, so the time needed for battles is not affected by the potions.
Given the list of battles, your task is to find a strategy to win all the battles as quickly as possible.
Note that you must enter the battles in order. You cannot redo or skip any battle.
Input
There will be at most 25 test cases. Each test begins with two integers n and p (1 ≤ n ≤ 1000,
1 ≤ p ≤ 100), the number of battles and your initial power. Each of the next n lines contains 6 integers
p1, p2, t1, t2, w1, w2 (1 ≤ p1 < p2 ≤ 100, 1 ≤ t2 < t1 ≤ 100, 0 ≤ w1, w2 ≤ 10). The input is terminated
by a test case with n = p = 0, you should not process it.
Output
For each test case, print the shortest time (in seconds) to win all the battles, to two digits after the
decimal point. If you cannot win all the battles, print ‘Impossible’ (without quotes).
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


题意:

前面有n只怪挡住了去路,勇士只能按顺序一只只解决,p为勇士力量。

每只怪有 p1,p2,t1,t2,w1,w2。

[p1,p2] 表示怪物护甲,[t2,t1] 表示解决一只怪的时间,w1为力量加+1药水数量,w2为力量翻倍药水数量,力量药水杀怪即送,喝药水不需要时间。

如果p<p1 无法战胜,p > p2 需要 t2秒,如果勇士战斗力在p1,p2之间,需要打败的时间线性减少。

求杀掉所有怪所需最短时间,无法战胜输出'Impossible'(不含引号)


思路:

w2可能要留着以后用更有效,但w1一有即饮。

p2最大为100,所以p最多只需100,w2最多只需要7瓶即可

dp[i][j][k] i为第i只怪,j为此时的力量,k为剩余w2数量。

p1<p<p2 时间计算公式为 (p2-p)/(p2-p1)*(t1-t2)+t2;

详见代码。


代码:

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

#define For(a,b,c) for(int a = b; a <= c; a++)
#define mem(a,b) memset(a,b,sizeof(a))
#define INF 1e10
#define eps 1e-6

double dp[1005][105][10];

int minint(int a, int b)
{
    return a < b ? a : b;
}

double mindouble (double a, double b)
{
    return a < b ? a : b;
}

double cal(int p,int p1,int p2,double t1,double t2) //计算所需时间
{
    if(p < p1) return INF;
    if(p > p2) return t2;
    return (1.0*p2-p)/(p2-p1)*(t1-t2)+t2;
}

int mypow(int a, int b)
{
    while(b--)
    {
        if(a > 100) return 100;
        a *= 2;
    }
    if(a > 100) return 100;
    return a;
}

int main()
{
    int n, p, p1, p2, w1, w2;
    double t1, t2;
    while(scanf("%d%d",&n,&p),n+p)
    {
        For(i,0,n) For(j,0,100) For(k,0,7) dp[i][j][k] = INF;

        dp[0][p][0] = 0;//第0只怪,p点力量,0瓶w2时时间耗费为0

        For(i,1,n)//下面,i为下次,i-1为本次
        {
            scanf("%d%d%lf%lf%d%d",&p1,&p2,&t1,&t2,&w1,&w2);
            For(j,p,100)
            {
                For(k,0,7)
                {
                    For(m,0,k+w2)//枚举喝药水数量,可以加上,m>7则退出循环
                    {
                        if(dp[i-1][j][k] < INF + eps && dp[i-1][j][k] > INF - eps) continue;//判断这种情况能否到达,不能则跳过

                        int p_fro = minint(100,j+w1);
                        int p_now = mypow(p_fro,m);//计算下次力量
                        int c = minint(k+w2-m,7);//下次剩余药水数量
                        //如果本次状态得到下次所需时间,如果能刷新下次的状态则刷新
                        dp[i][p_now][c] = mindouble(dp[i][p_now][c], dp[i-1][j][k]+cal(j,p1,p2,t1,t2));
                    }
                }
            }
        }

        double ans = INF;
        For(i,p,100)
            For(j,0,7)
                if(dp[n][i][j] < ans)
                    ans = dp[n][i][j];
        if(ans < INF + eps && ans > INF - eps) printf("Impossible\n");
        else printf("%.2lf\n",ans);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值