poj 3756

题目描述:

类似大富翁的游戏,给你一条长度为n的条状棋盘,起点为0号,终点为n号,一共有n 1个点。

每个点有4种状态:

1:无状态。

2:从此点往前走k步。

3:从此点往后退m步。

4:下一回合不能动。

每一回合仅能启用一种状态(比如中了状态2往前走k步后,刚好又碰到状态3,则状态3不起作用)

如果退到0点或者n点还有剩余的步可以走,则往相反的方向走(既不能丢弃多余的步,也不能走出棋盘)。

问你从0走到n所需的回合的期望。

解题报告:

dp,dp[i][j]表示第i回合走到第j号点的概率是多少,开始时dp[0][0] = 1,其他都为0.

若dp[i][j] != 0, 根据规则,容易求的从j开始抛骰子的以下六个位置记作pos[k], 0<= k < 6

如果走到pos[k]是启用的是状态4(下一回合不能动)

则dp[i+2][pos[k]]+ = dp[i][j] * (1 / 6)

否则 dp[i+1][pos[k]]+ = dp[i][j] * (1 / 6)

代码:

 
  
#include < iostream >
#include
< fstream >

using namespace std;

int num1,num2,num3;
int a[ 101 ];
int b[ 101 ],c[ 101 ];
double dp[ 300 ][ 101 ];
int n;

int ok( int s){

while ( 1 ){
if (s > n) s = 2 * n - s;
else if (s < 0 ) s =- s;
else return s;
}
}

void read(){
// ifstream cin("in.txt");
int i,j,k;
cin
>> n;
cin
>> num1;
for (i = 1 ;i <= num1;i ++ )
{
cin
>> j >> k;
a[j]
= 1 ;
b[j]
= k;
}
cin
>> num2;
for (i = 1 ;i <= num2;i ++ )
{
cin
>> j >> k;
a[j]
= 2 ;
c[j]
= k;
}
cin
>> num3;
for (i = 1 ;i <= num3;i ++ )
{
cin
>> j;
a[j]
= 3 ;
}
dp[
0 ][ 0 ] = 1 ;
for (i = 0 ;i < 200 ;i ++ )
{
for (j = 0 ;j < n;j ++ )
if (dp[i][j] > 0 )
{
for (k = 1 ;k <= 6 ;k ++ )
{
int s = ok(j + k);
if (a[s] == 3 )
{
dp[i
+ 2 ][s] += dp[i][j] * 1 / 6 ;
}
else
{
if (a[s] == 1 ) s = ok(b[s] + s);
else if (a[s] == 2 ) s = ok(s - c[s]);
dp[i
+ 1 ][s] += dp[i][j] * 1 / 6 ;
}
}
}
}
double ans = 0 ;
for (i = 1 ;i < 200 ;i ++ )
ans
+= i * dp[i][n];

if (ans < 0.005 )
printf(
" Impossible\n " );
else
printf(
" %.2lf\n " ,ans);

}


int main(){
read();
return 0 ;
}

转载于:https://www.cnblogs.com/zhaozhe/archive/2011/02/24/1963768.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值