第 45 届国际大学生程序设计竞赛(ICPC)亚洲网上区域赛模拟赛 D.Pokemon Ultra Sun(dp动态规划)

题目链接:https://ac.nowcoder.com/acm/contest/8688/D

题目描述
Two pokemons are in a battle.One is our and another is the opposite’s.

Our pokemon is in confusion and the opposite’s pokemon is frozen.

Once per turn , the opposite’s pokemon does nothing and our pokemon gives w damages to the opposite’s pokemon with a probability of P while gives w damages to itself with a probability of 1 − P.

Our pokemon has hp1 health points and the opposite’s pokemon has hp2 health points.

If one pokemon’s health points are zero or below zero, the game is over.

Your task is to calculate the expected number of turn.

输入描述:
The first line is an integer T(T ≤ 8) , the number of test cases.

For each test case, the first line contains three integers hp1, hp2, w(1 ≤ hp1, hp2, w ≤ 3000), representing our pokemon’s health points, the opposite’s health points and damage. The second line contains a real number P(0 < P < 1). which is described above.

输出描述:
For each test case, print the expected number of turn rounding to 6 digits after decimal in one line.

示例1

输入

1
1 1 1
0.5

输出

1.000000

题意

给出两个宝可梦,各有 hp1 hp2 的血量,第一个宝可梦的攻击力为 w ,每一回合有 p 的概率对对方造成 w 的伤害,1-p 的概率对自己造成 w 伤害,求能进行的回合的期望。

分析

我们设 dp[i][j] 表示两个宝可梦的血量分别为 i ,j 时的期望。
动态转移方程就是
dp[i][j] = (1 - p) * (dp[i - w][j] + 1) + p * (dp[i][j - w] + 1)(注意 i 或 j 小于 w 时的情况)
边界:dp[1][1] 的期望一定是 1 ;i 和 j 中有一个为 0 ,则期望一定为 0 。

代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
 
int t;
int hp1,hp2,w;
double p;
double dp[3005][3005];
 
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        memset(dp, 0, sizeof(dp));
        scanf("%d%d%d%lf",&hp1,&hp2,&w,&p);
        dp[1][1] = 1;
        for(int i=1;i<=hp1;i++)
            for(int j=1;j<=hp2;j++)
            {
                double temp1,temp2;
                if(i - w < 0) temp1 = 0;
                else temp1 = dp[i - w][j];
                if(j - w < 0) temp2 = 0;
                else temp2 = dp[i][j - w];
                dp[i][j] = (1 - p) * (temp1 + 1.0) + p * (temp2 + 1.0);
            }
        printf("%.6lf\n",dp[hp1][hp2]);
    }
    return 0;  
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值