题目描述:
类似大富翁的游戏,给你一条长度为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 ;
}
#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 ;
}