[问题描述] 玩家根据骰子的点数决定走的步数,即骰子点数为1时可以走一步,点数为2时可以走两步,点数为n时可以走n步。求玩家走到第n步(n <= 骰子最大点数且投骰子方法唯一)时总共有多少种投骰子的方法数.
[输入描述] 输入包含一个整数n(1 <= n <= 6)
[输出描述] 输出一个整数,表示投骰子的方法数。
[输入样例] 6
[样例输出] 32
[思路] 设f(n)表示玩家走到第n步时投骰子的方法数。显然:
n = 1时,只有投骰子点数为1的一种情况。即f(1) = 1.
n = 2时,只有两次投骰子点数为1和一次投骰子点数为2的两种情况。即f(2) = 2
对于n,第一次投骰子点数为1,剩余n-1步,此时f(n) = f(n-1);第一次投骰子点数为2,剩余n-2步,此时f(n)=f(n-2);…第一次投骰子点数为n,只有一种情况,此时f(n)=1.所以有f(n)=f(n-1)+f(n-2)+f(n-3)+…+f(1)+1
对应的递归模型如下:
f
(
n
)
=
{
1
,
当
n
=
1
时
2
,
当
n
=
2
时
f
(
n
−
1
)
+
f
(
n
−
2
)
+
.
.
.
.
f
(
1
)
+
1
,
当
n
>
2
时
f(n)=\begin{cases} 1,当n=1时\\ 2,当n=2时\\ f(n-1)+f(n-2)+....f(1)+1,当n>2时 \end{cases}
f(n)=⎩⎪⎨⎪⎧1,当n=1时2,当n=2时f(n−1)+f(n−2)+....f(1)+1,当n>2时
可以采用以下递归算法求解:
long f(int n)
{
if(n == 1)
{
return 1;
}
if(n == 2)
{
return 2;
}
long sum = 1;
for(int i = 1;i <= n - 1;i++)
{
sum += f(i);
}
}
一个更优的方法是采用非递归方法。看看前面递归模型的递推过程,可以总结出如下的递推关系。
f(1) = 1
f(2) = 2
f(3) = f(2) + f(1) + 1 = (2 + 1) + 1 = 2的平方 - 1 + 1 = 2的平方
f(4) = f(3) + f(2) + f(1) + 1 = (2的平方 + 2 + 1) + 1 = 2的3次方 - 1 + 1 = 2的3次方
f(5) = f(4) + f(3) + f(2) + f(1) + 1 = (2的三次方 + 2的平方 + 2 + 1) + 1 = 2的四次方 - 1 + 1 = 2的4次方
依次类推,可以得到f(n) = 2n-1 .对应的完整程序如下:
[完整程序]
#include <iostream>
using namespace std;
int main()
{
int n;
cin >> n;
cout << (long)pow(2,n-1) << endl;
return 0;
}