ZOJ 3329 One Person Game (概率dp)
2014-04-20 22:00
477 查看
OJ题目:click here~~
题目分析: 有一个计数器 , 初值为0。三个骰子 ,分别有k1, k2, k3面,每个骰子,每面向上的概率相等。给三个数a , b , c。 游戏如下:1,计数器初值设为0。 2,同时掷三个骰子,如果骰子1出现a , 骰子2出现b, 骰子3出现c, 则将计数器设为0,否则将三个数字的和加到计数器上。3,如果此时计数器的数字仍然不超过n , 则回到第2步 , 否则游戏结束。求游戏结束前掷骰子的次数的期望。
设dp[ i ] 为计数器上的数字为 i 时 ,离目标状态的期望步数。显然dp[ 0 ] 是要求的值。
则 dp[ i ] = p0*dp[ 0 ] + sigma dp[ i + k]*p[ k ] + 1, k 从 3 到(k1 + k2 + k3)--------- 1
由式子1可知,dp[ i ] 由dp[ 0 ] 表示 , 而dp[ 0 ] 是我们要求的 ,则将dp[ i + k] 也用dp[ 0] 表示。
设:dp[ i ] = a[ i ] * dp[ 0 ] + b[ i ] ---------- 2
将2式带入1 , dp[ i ] = p0*dp[ 0 ] + sigma (a[ i + k] * dp[ 0 ] + b[ i + k])*p[ k ] + 1
整理可得:dp[ i ] = (sigma a[ i + k]*p[ k ] + p0 )*dp[ 0 ] + sigma b[ i + k]*p[ k ] + 1 -----------3
对比3式和1式 , 可得:
a[ i ] = sigma a[ i + k]*p[ k ] + p0
b[ i ] = sigma b[ i + k]*p[ k ] + 1
又当i > n , dp[ i ] = 0 , 由2式 , 可得
a[ i ] = b[ i ] = 0;
至此,可按i 从大到小 , 求出a[ n ] , b [ n] --- ---- ---- a[ 0 ] , b[ 0 ];
最后由2式 ,
dp[ 0 ] = b[ 0 ] / (1 - a[ 0 ]) ;
AC_CODE
double p[38];
int main()
{
//freopen("in.txt","r",stdin);
int t;
cin >> t;
while(t--){
int n , k1, k2, k3 , aa, bb , cc;
cin >> n >> k1 >> k2 >> k3 >> aa >> bb >> cc;
memset(p , 0 , sizeof(p));
double a[536] = {0};
double b[536] = {0};
double p0 = 1.0/(k1*k2*k3);
int i , j , k;
for(i = 1;i <= k1;i++)
for(j = 1;j <= k2;j++)
for(k = 1;k <= k3;k++)
if(i == aa && j == bb && k == cc) continue;
else p[i + j + k] += p0;
for(i = n;i >= 0;i--){
for(k = 3;k <= (k1+k2+k3);k++){
a[i] += p[k]*a[i+k];
b[i] += p[k]*b[i+k];
}
a[i] += p0;
b[i] += 1;
}
double ans = b[0] / (1 - a[0]);
printf("%.15lf\n",ans);
}
return 0;
}
题目分析: 有一个计数器 , 初值为0。三个骰子 ,分别有k1, k2, k3面,每个骰子,每面向上的概率相等。给三个数a , b , c。 游戏如下:1,计数器初值设为0。 2,同时掷三个骰子,如果骰子1出现a , 骰子2出现b, 骰子3出现c, 则将计数器设为0,否则将三个数字的和加到计数器上。3,如果此时计数器的数字仍然不超过n , 则回到第2步 , 否则游戏结束。求游戏结束前掷骰子的次数的期望。
设dp[ i ] 为计数器上的数字为 i 时 ,离目标状态的期望步数。显然dp[ 0 ] 是要求的值。
则 dp[ i ] = p0*dp[ 0 ] + sigma dp[ i + k]*p[ k ] + 1, k 从 3 到(k1 + k2 + k3)--------- 1
由式子1可知,dp[ i ] 由dp[ 0 ] 表示 , 而dp[ 0 ] 是我们要求的 ,则将dp[ i + k] 也用dp[ 0] 表示。
设:dp[ i ] = a[ i ] * dp[ 0 ] + b[ i ] ---------- 2
将2式带入1 , dp[ i ] = p0*dp[ 0 ] + sigma (a[ i + k] * dp[ 0 ] + b[ i + k])*p[ k ] + 1
整理可得:dp[ i ] = (sigma a[ i + k]*p[ k ] + p0 )*dp[ 0 ] + sigma b[ i + k]*p[ k ] + 1 -----------3
对比3式和1式 , 可得:
a[ i ] = sigma a[ i + k]*p[ k ] + p0
b[ i ] = sigma b[ i + k]*p[ k ] + 1
又当i > n , dp[ i ] = 0 , 由2式 , 可得
a[ i ] = b[ i ] = 0;
至此,可按i 从大到小 , 求出a[ n ] , b [ n] --- ---- ---- a[ 0 ] , b[ 0 ];
最后由2式 ,
dp[ 0 ] = b[ 0 ] / (1 - a[ 0 ]) ;
AC_CODE
double p[38];
int main()
{
//freopen("in.txt","r",stdin);
int t;
cin >> t;
while(t--){
int n , k1, k2, k3 , aa, bb , cc;
cin >> n >> k1 >> k2 >> k3 >> aa >> bb >> cc;
memset(p , 0 , sizeof(p));
double a[536] = {0};
double b[536] = {0};
double p0 = 1.0/(k1*k2*k3);
int i , j , k;
for(i = 1;i <= k1;i++)
for(j = 1;j <= k2;j++)
for(k = 1;k <= k3;k++)
if(i == aa && j == bb && k == cc) continue;
else p[i + j + k] += p0;
for(i = n;i >= 0;i--){
for(k = 3;k <= (k1+k2+k3);k++){
a[i] += p[k]*a[i+k];
b[i] += p[k]*b[i+k];
}
a[i] += p0;
b[i] += 1;
}
double ans = b[0] / (1 - a[0]);
printf("%.15lf\n",ans);
}
return 0;
}
相关文章推荐
- ZOJ 3329 One Person Game 概率DP
- zoj 3329 One Person Game(概率DP基础)
- ZOJ 3329 One Person Game (经典概率dp+有环方程求解)
- [ACM] ZOJ 3329 One Person Game (概率DP,有环,巧妙转化)
- zoj 3329 One Person Game (概率DP )
- ZOJ 3329 One Person Game 概率DP
- ZOJ 3329 One Person Game 带环的概率DP
- ZOJ 3329 One Person Game(概率DP)
- ZOJ 3329 One Person Game 概率dp 处理环
- ZOJ-3329 One Person Game (概率DP)
- ZOJ 3329 One Person Game 带环的概率DP
- ZOJ 3329 One Person Game(概率dp 经典)
- ZOJ 3329 One Person Game (概率DP)
- ZOJ 3329 One Person Game(概率DP,求期望)★
- zoj 3329 One Person Game(概率dp,期望)
- zoj 3329 One Person Game (有环 的 概率dp)
- ZOJ 3329 One Person Game(概率DP、求期望)
- zoj 3329 One Person Game 概率dp
- ZOJ 3329 One Person Game(概率dp)
- ZOJ 3329 One Person Game(概率DP)