【方案数】 递推如何解决?CCF1171

     本文为作者原创。

这是我第一次写博客,不便之处请谅解。

方案数

 

题目描述:

有一个类似弹球的游戏,如下图,小球从上下滑落,每次到一个交叉点都有两种选择:向左或向右滑落,如果有一个球从顶端滑落到低端有多少种走法?特别是交叉点中有一些陷阱,小球掉进陷阱就不能走了。

 

首先来看一下样例:

        1.定义了一个四行的三角形

        2.三排第二个点是陷阱

 

        不难理解,小球从上方到第三行路径有2条,第四行有4条,所以一共只有4条路径可走。

如果用递归,那么我们要从顶部往下,每一个点都引申出左下和右下两个点,每当遇上陷阱,就返回0,  表示没有路可走。

但这样太慢了!

 

       为什么呢?

因为跟数字三角形那一道经典题一样,递归的点重复了,三角形的行数越多,重复调用的次数更是翻倍激增。

       那么该如何解决呢?

我们可以用递归

递归思路:

      1.把三角形底部都设置成1

      2.从下往上递推,两个点相加放在上面那个点里

      3.遇上陷阱就把上面那一个点变为0

      4.最上面的点就是结果了

代码实现:

 1 #include<cstdio>
 2 #include<iostream>
 3 using namespace std;
 4 int main(){
 5     int a[100][100],n,m,x,y;
 6     cin>>n>>m;
 7     for(int i=0;i<m;++i){
 8         cin>>x>>y;
 9         a[x-1][y-1]=-1;//标志陷阱
10     }
11     for(int i=0;i<n;++i){
12         a[n-1][i]=1;//第一步
13     }
14     for(int i=n-2;i>=0;i--){
15         for(int j=0;j<=i;j++){
16             if(a[i][j]==-1){
17                 a[i][j]=0;//第三步
18                 continue;
19             }
20             else {
21                 a[i][j]=a[i+1][j]+a[i+1][j+1];//第二步
22             }
23         }
24     }
25     cout<<a[0][0];//第四步
26     return 0;
27 }

于是题目就通过了!

时间复杂度:O(n)。

posted on 2017-09-10 20:05  Come-true!  阅读(76)  评论(0)    收藏  举报

导航