您的位置:首页 > 其它

CSUOJ 赌神的战斗

2015-08-13 13:04 239 查看


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
****************************************************************/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: