弹球II 解题报告

题目:

弹球II
Time Limit:1000MS Memory Limit:65536K
Description
游戏厅里有一种很常见的游戏机,里面有很多根管子有规律地排成许多行。小球
从最上面掉下去,碰到管子会等概率地往管子左边或者右边的空隙掉下去。不过
在最靠边的小球只会往一边掉(如图,灰色小球只可能掉到右边空隙)。现在已
知共2 * n - 1 行管子,第i 行有Ai 个管子,如果i 是奇数,那么Ai 等于m,如
果i 是偶数,Ai 等于m - 1。小球从第1 行第k 个管子右边掉下去,要求小球从
最后一行各个出口掉出来的概率。


Input
第一行是一个整数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 个管子右边掉下去。
Output
输出m-1 个小数,第i 个数表示小球从最后一行第i 个出口出来的概率。
每个小数保留小数点后六位,小数与小数之间用一个空格隔开。
Sample Input
1
3 3
2
Sample Output
0.375000 0.625000

解题思路:

   本题是计算概率的问题,也就是从顶端扔下一个小球,输出在下面每个出口处的概率的大侠,精确到小数点后的第六位。在奇数行,总有偶数跟柱子,有奇数个空,在偶数行,总有奇数个柱子,偶数个空,而且奇数和偶数交替进行。第一行和最后一行都是奇数行,所以开始和结束的空总是相同的。解决本题,设两个一维数组,进行一次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<iomanip>
using namespace std;
int main()
{
int T;
cin>>T;
while(T--)
{
int n,m;
cin>>n;
cin>>m;
double f[11]={0};
double f1[11]={0};
int k;
cin>>k;
f[k]=1;
if(m==2)
           cout<<setprecision(6)<<fixed<<(double)(m-1)<<endl;                m=2,则开始和结束只有一个空,概率当然为1.
else
{
 int b;
 int i,j;
 for(b=2;b<=2*n-1;b++)
 {
if(b%2)                                                                                  奇数行进行的操作
{
for(i=1;i<m;i++)
{
j=i;
if(i==1)
{
f1[i]=(2*f[j]+f[j+1])/2.0;
}
else if(i==m-1)
f1[i]=(2*f[j+1]+f[j])/2.0;
else
f1[i]=(f[j]+f[j+1])/2.0;
}
for(i=1;i<m;i++)                                                把概率复制给f数组,同时f[m]置0;
f[i]=f1[i];
f[m]=0;
}
else                                                                         偶数行进行的操作
{
for(i=1;i<=m;i++)
{
j=i;
if(i==1)
f1[i]=f[j]/2.0;
else if(i==m)
f1[i]=f[j-1]/2.0;
else
f1[i]=(f[j-1]+f[j])/2.0;
}
  for(i=1;i<=m;i++)
f[i]=f1[i];
}
 }
 for(i=1;i<m-1;i++)
 cout<<setprecision(6)<<fixed<<f[i]<<" ";                                                    格式控制输出,避免多输出一个空格,顾进行两次操作。
 cout<<setprecision(6)<<fixed<<f[m-1]<<endl;
}
}
return 0;
}

解题感想:

    经过一段时间的训练,发现所有较难的题目,要不是有固定的模板,要不就有可以简化的算法思路,所以在解决类似这道题的问题时,最主要的是发现他们之间的相互规律,只有这样,才能简化这道题的,不然的话,就难以下手去做,解决这道题也是受到大神的启发,然后细心琢磨之后解决出来了,不过发现自己写的代码号繁琐,以后还要逐渐精简代码,使之简单易懂,总之,以后碰到类似的问题,还要从数学的思维入手,然后结合自身的计算机算法知识来解决,不过首先还是要有数学思想才可以,以后还要多加练习,争取自己也成为一个大神。







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值