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;
}

posted on 2011-02-24 14:26  宇宙吾心  阅读(441)  评论(1编辑  收藏  举报

导航