Description
老千可以有很多,但是赌神,只能有一个!
2015届赌神争霸赛现在在湖南长沙淹鱼塘隆重开幕,2名赌神候选者已经准备就绪。
已知赌神争霸的规则如下:
每个赌神候选者有一个他特制的骰子和特制的战甲,分别能给他提供攻击力和生命值。
两个赌神候选者交手的流程如下:
1,2号赌神候选者分别投掷自己的骰子,点数相同则重新投,否则点数大的赌神候选者会对点数小的造成他们点数差的伤害。如果承受伤害之后生命值小于或等于零,则战败。否则,进行下一轮交手。(投掷出来的点数在
上
均匀分布)
Input
多组数据,第一行有一个整数
T
,表示有
T
组数据。(
T<=100
)
以下每组数据
每行
有
四
个整数
ATK1,HP1
和
ATK2,HP2
,
ATK1和HP1
表示
1号赌神
候选者
的骰子最大点数和他的血量,ATK2和HP2
表示
2号赌神
候选者
的骰子最大点数和他的血量
。
(1<=
ATK1
,
HP1
,
ATK2
,
HP2
<=
200
)
Output
两个浮点数(精确到小数点后三位),为1号赌神的胜率和2号赌神的胜率。
Sample Input
2
6 1 6 1
1 24 2 1
Sample Output
0.500 0.500
0.000 1.000
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////分析:
概率DP。用两者的血量为下标建立二维DP数组,并预处理玩家1和玩家2被扣血量x时的概率分别为g1[x]、g2[x]。状态转移dp[i][j]+=dp[i][j+q]*g1[q]+dp[i+p][j]*g2[p遍历完所有的q、p之后再除去平局的情况:dp[i][j]=dp[i][j]/(1-g1[0]) 这里g1[0]和g2[0]都行,是相等的。
下面是代码:(我觉得自己的代码一直都是无比暴力的。。。)
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
double g1[500],g2[500];
double dp[500][500];
int t,h1,h2,k1,k2;
void init()
{
memset(g1,0,sizeof(g1));
memset(g2,0,sizeof(g2));
double p1,p2;
p1=(double)1.0/k1;
p2=(double)1.0/k2;
for(int i=1;i<=k1;++i){
for(int j=1;j<=k2;++j){
if(i>j)g2[i-j]+=p1*p2;
else if(i<j)g1[j-i]+=p1*p2;
else{g1[0]+=p1*p2;g2[0]+=p1*p2;}
}
}
}
int main()
{
/// freopen("in.txt","r",stdin);
scanf("%d",&t);
while(t--){
scanf("%d%d%d%d",&k1,&h1,&k2,&h2);
if(k1==1&&k2==1){
printf("0.000 0.000\n");
continue;
}
memset(dp,0,sizeof(dp)); init();
dp[h1][h2]=1.0;
double vic1,vic2;
vic1=0.0;vic2=0.0;
for(int i=h1;i>0;--i){
for(int j=h2;j>0;--j){
for(int k=1;k<=k1;++k){
dp[i][j]+=dp[i][j+k]*g2[k];
}
for(int k=1;k<=k2;++k){
dp[i][j]+=dp[i+k][j]*g1[k];
}
if(i!=h1||j!=h2)dp[i][j]=dp[i][j]/(1-g1[0]);///***这一步很重要
}
for(int k=1;k<=k1;++k){
for(int b=1;b<=k;++b){
dp[i][0]+=dp[i][b]*g2[k];
}
}
dp[i][0]=dp[i][0]/(1-g1[0]);////**这一步很重要
vic1+=dp[i][0];
}
for(int j=1;j<=h2;++j){
for(int k=1;k<=k2;++k){
for(int b=1;b<=k;++b){
dp[0][j]+=dp[b][j]*g1[k];
}
}
dp[0][j]=dp[0][j]/(1-g1[0]);///***这一步很重要
vic2+=dp[0][j];
}
printf("%.3lf %.3lf\n",vic1,vic2);
}
return 0;
}
/**************************************************************
Problem: 1670
User: 504772261
Language: C++
Result: Accepted
Time:2408 ms
Memory:2924 kb
****************************************************************/