弹球II
描述-
游戏厅里有一种很常见的游戏机,里面有很多根管子有规律地排成许多行。小球从最上面掉下去,碰到管子会等概率地往管子左边或者右边的空隙掉下去。不过在最靠边的小球只会往一边掉(如图,灰色小球只可能掉到右边空隙)。现在已知共2 * n - 1行第k个管子右边掉下去,要求小球从最后一行各个出口掉出来的概率。
-
-
输入
-
第一行是一个整数t(1≤t≤50),表示有t组测试数据。
每组数据第一行有两个整数n(1≤n≤100)和m(2≤m≤10),表示有2*n-1行管子,奇数行有m个管子,偶数行有m-1个管子。
第二行是一个整数k(1≤k≤m-1),表示小球从第1行第k个管子右边掉下去。
输出
-
输出m-1个小数,第i个数表示小球从最后一行第i个出口出来的概率。
每个小数保留小数点后六位,小数与小数之间用一个空格隔开。
样例输入
-
1 3 3 2
样例输出
-
0.375000 0.625000
来源
- GDUT校赛 上传者
- ACM_李如兵
本题是计算概率的问题,也就是从顶端扔下一个小球,输出在下面每个出口处的概率的大侠,精确到小数点后的第六位。在奇数行,总有偶数跟柱子,有奇数个空,在偶数行,总有奇数个柱子,偶数个空,而且奇数和偶数交替进行。第一行和最后一行都是奇数行,所以开始和结束的空总是相同的。解决本题,设两个一维数组,进行一次for循环即可。分别为a[11],b[11]。在第一行第k个空投入,则a[k]=1;在第二行,则有a[k]=a[k+1]=0.5;可以看出。每两行之间遵从这样的规律,从奇数行到偶数行,a[k]=(a[k]+a[k+1])/2.0;边界处有a[1]=a[i]/2.0,a[m-1]=a[m]/2.0;之后a[m]赋值为0,因为偶数行没有第m个空,同样从偶数行到奇数行,也遵从相同规律,也之后边界处不同,在边界处有a[1]=a[1]+(a[2]/2.0),a[m]=a[m-1]/2.0;只要把握好这个规律,解决这道题就算是很简单的问题了
-
#include<iostream> #include<stdio.h> #include<cstring> using namespace std; double mm[210][12]; int main() { int t,n,m,k,i,j; scanf("%d",&t); while(t--) { memset(mm,0,sizeof(mm)); scanf("%d%d%d",&n,&m,&k); if(m==2) printf("1.000000\n"); else { mm[1][k]=1; for(i=2;i<=2*n-1;i++) { if(i%2==0) { mm[i][1]=mm[i-1][1]/2;//处理边界情况 mm[i][m]=mm[i-1][m-1]/2; for(j=2;j<m;j++) mm[i][j]=(mm[i-1][j-1]+mm[i-1][j])/2; } else { mm[i][1]=mm[i-1][1]+mm[i-1][2]/2; mm[i][m-1]=mm[i-1][m-1]/2+mm[i-1][m]; for(j=2;j<m-1;j++) mm[i][j]=(mm[i-1][j]+mm[i-1][j+1])/2; } } printf("%.6lf",mm[i-1][1]); for(j=2;j<m;j++) printf(" %.6lf",mm[i-1][j]); printf("\n"); } } return 0; }
-
-
-
-
-
-
-