洛谷P1057 传球游戏
题目链接:https://www.luogu.org/problem/P1057
题目思路:
首先我们来看这道题,意思是说n个人,从1开始每个数都可以向左或向右移动一个单位,求移动m次后又回到1的方式
比如2个人 1 2 从1开始:移动2次回到1的方式只有1种。如果只移动1次,那永远回不到1。
那如果只移动0次的话,相当于没有移动。若当前位置就是1,那就是一种方法,即不移动,若当前位置不是1,说明移动一次无法到达1,所以是0种。
下面代码中, return 0 和 return 1的问题就是上面的理解。接下来用ans存储结果。因为一个数只能向左或向右走,并且由于围成一个圈,这里要考虑两种特殊情况:1的左边是n,n的右边是1,其余情况就是i-1和i+1(i为当前的位置)。所以移动m次到i的问题就可以分解成两个子问题,结果即移动m-1次到i的左边的个数 和 移动m-1次到i的右边的个数的和。
(PS:初始位置其实可以是1~n任意一个哒,这里图方便就选了1 =_=)
参考代码:
#include<bits/stdc++.h>
using namespace std;
int n,m,dp[100][100];
int main()
{
cin>>n>>m;//n个同学,传m次球
for(int i=1;i<=100;i++)
dp[0][i]=0;
dp[0][1]=1;
for(int i=1;i<=m;i++)//传球次数
for(int j=1;j<=n;j++)
{
int left= (j==1 ? n:j-1);
int right=(j==n ? 1:j+1);
dp[i][j]=dp[i-1][left]+dp[i-1][right];
//dp[i][j]表示经过i次传到编号为j的人手中的方案数,传到j号同学的球只能来自于j的左边一个同学和右边一个同学,
//这两个同学的编号分别是left和right,所以可以得到以下的递推公式:dp[i][j]=dp[i-1][left]+dp[i-1][right];
}
cout<<dp[m][1];
return 0;
}