法一:
//2015/4/14
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
#define N 60
int n, m, num;
bool tra[N*N]; //表示是否有钉子,true则有,false则无
long long dp[N][N]; //因为钉子最多有50层,2<<50超出了int的表示范围,所以要用long long类型(64位整数)
long long fz, fm, ubt; //分子, 分母 , 最大公约数
long long gcd(long long a, long long b) //求最大公约数
{
long long mod;
while (b)
{
mod = a%b;
a = b;
b = mod;
}
return a;
}
void go()
{
num = 0; //表示序号
char str[4]; //存放字符
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= i; j++)
{
scanf("%s", str);
if (str[0] == '*') //为‘*’则有钉子
{
tra[++num] = true;
}
else
{
tra[++num] = false;
}
}
}
memset(dp, 0, sizeof(dp));
dp[1][1] = 1LL << n; ////用位运算计算2 ^ n
for (int i = 1, sbh; i <= n; i++)
{
sbh = (i*(i - 1)) / 2; //记录位置
for (int j = 1; j <= i; j++)
{
if (tra[j + sbh]) //遇到钉子
{
//当某个位置(i, j)的钉子在,则将该位置的概率除以1 / 2再传递到(i + 1, j)和(i + 1, j + 1)两个位置
dp[i + 1][j] += dp[i][j] / 2;
dp[i + 1][j + 1] += dp[i][j] / 2;
}
else
{
//如果某个位置钉子不在了,则该位置的概率垂直下落到下下层对应位置,即(i,j)处的概率直接赋予位置(I+2, j+1)
dp[i + 2][j + 1] += dp[i][j];
}
}
}
fz = dp[n + 1][m + 1];
fm = 1LL << n; //用位运算计算2 ^ n
ubt = gcd(fm, fz); //计算最大公约数
if (fz == 0)
{
fm = ubt = 1;
}
printf("%I64d/%I64d\n", fz / ubt, fm / ubt);
}
int main()
{
// freopen("E:\input.txt", "r", stdin);
while (scanf("%d%d", &n, &m) != EOF)
{
go();
}
return 0;
}
#include "stdio.h"
#include "string.h"
#define M 55
#define ll __int64
int a[M][M],n,m;
ll dp[M][M];
char s[5];
ll gcd(ll a,ll b)
{
if(b)
return gcd(b,a%b);
return a;
}
int main()
{
// freopen("E:\input.txt", "r", stdin);
int i,j;
ll ans1,ans2;
ll k;
while(scanf("%d%d",&n,&m)>0)
{
memset(dp,0,sizeof(dp));
for(i=0;i<n;i++)
{
for(j=0;j<=i;j++)
{
scanf("%s",s);
if(s[0]=='*')
a[i][j]=1;
else a[i][j]=0;
}
}
dp[0][0]=1;
for(i=0;i<n;i++)
dp[0][0]*=2;
for(i=0;i<n;i++)
{
for(j=0;j<=i;j++)
{
if(a[i][j]) //遇到钉子
{
dp[i+1][j] += dp[i][j]>>1;
dp[i+1][j+1] += dp[i][j]>>1;
}//没遇到
else dp[i+2][j+1] += dp[i][j];
}
}
ans1=dp[n][m];
ans2=0;
for(i=0;i<=n;i++)
ans2+=dp[n][i];
k=gcd(ans1,ans2);
if(ans1==0)
{
ans2=1;k=1;
}
printf("%I64d/%I64d\n",ans1/k,ans2/k);
}
return 0;
}

本文介绍了两种解决钉子概率问题的方法。通过分析钉子的存在与否来计算从起点到达终点的概率,并采用分数形式给出最终答案。第一种方法使用位运算进行概率计算;第二种方法则通过数组记录钉子状态,利用递推公式更新概率。
279

被折叠的 条评论
为什么被折叠?



