洛谷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;
}

posted @ 2019-08-24 15:16  如梦山河乀  阅读(108)  评论(0编辑  收藏  举报