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
HINT
自己写的时候只考虑了单个人,没有注意到概率与两人都有关,还是自己对概率和期望的计算太过陌生,话说现在我还没理解好期望的递推。。。
下面有两份代码,第一份是比赛时的题解,但当时数据比较水,此份代码可以通过,后来这题挂到oj后,数据又加强了,此种解法就超时了,第二份代码是优化后的代码,这个其实是我在比赛时想的优化方法,但递推关系没想好,然后就wa wa wa。。 。
另外解释一下第二份代码的思路: hehe函数处理两个数组a b, a[i]代表 赌神一对赌神二造成i点伤害的概率,同理,b[i]代表赌神二对一造成i点伤害的概率,注意到这里的概率去除了两者点数相同的情况,此外还需要注意的一点是最后计算两者赢的概率时不可用1减某一方赢的概率,因为这样会忽略两者赢的概率都为0的情况。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
double dp[480][480] ;
int main()
{
// freopen("data.in", "r",stdin) ;
int T ;
scanf("%d", &T) ;
while(T--)
{
int atk1,hp1,atk2,hp2;
scanf("%d%d%d%d", &atk1, &hp1, &atk2 , &hp2) ;
memset(dp , 0 , sizeof(dp)) ;
dp[hp1][hp2] = 1.0;
double transp = 1.0 / (atk1 * atk2 - min(atk1 , atk2)) ;
for(int i=hp1; i>0; i--)
{
for(int j=hp2; j>0; j--)
{
for(int t1=1; t1<=atk1 ; t1++)
{
for(int t2=1; t2<=atk2; t2++)
{
int dif = abs(t1 - t2) ;
if(t1 > t2) dp[i][max(j-dif,0)] += dp[i][j] *transp ;
if(t2 > t1) dp[max(i-dif,0)][j] += dp[i][j] *transp ;
}
}
}
}
double ans1=0, ans2=0 ;
for(int i=1; i<=hp1; i++)
ans1 += dp[i][0] ;
for(int i=1; i<=hp2; i++)
ans2 += dp[0][i] ;
printf("%.3f %.3f\n" , ans1, ans2);
}
return 0;
}
#include <cstdio>
#include <cstring>
#include <math.h>
using namespace std;
double dp[480][480];
double tmp;
int h1,n1,h2,n2;
double a[450],b[450];
int max(int x,int y)
{
return x>y?x:y;
}
void hehe()
{
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
double x=1.0/n1,y=1.0/n2;
for(int i=1;i<=n1;i++)
{
for(int j=1;j<=n2;j++)
{
if(i==j)
{
a[0]+=x*y;
b[0]=a[0];
}
else if(i>j)
a[i-j]+=x*y;
else if(i<j)
b[j-i]+=x*y;
}
}
double sum=0;
for(int i=1;i<n1;i++)
{
sum+=a[i];
}
for(int i=1;i<n2;i++)
{
sum+=b[i];
}
for(int i=1;i<n1;i++)
a[i]=a[i]/sum;
for(int i=1;i<n2;i++)
b[i]=b[i]/sum;
}
int main()
{
freopen("in.txt","r",stdin);
int t;
scanf("%d",&t);
while(t--)
{
memset(dp,0,sizeof(dp));
scanf("%d%d%d%d",&n1,&h1,&n2,&h2);
hehe();
dp[h1][h2]=1;
for(int i=h1;i>0;i--)
{
for(int j=h2;j>0;j--)
{
for(int k=1;k<n2;k++)
dp[max(i-k,0)][j]+=dp[i][j]*b[k];
for(int k=1;k<n1;k++)
dp[i][max(j-k,0)]+=dp[i][j]*a[k];
}
}
double ans1=0,ans2=0;
for(int i=1;i<=h1;i++)
{
ans1+=dp[i][0];
}
for(int i=1;i<=h2;i++)
ans2+=dp[0][i];
printf("%.3lf %.3lf\n",ans1,ans2);
}
}