这题用dp或者dfs都能做,对于新手最不友好的就是dp了,这里说明一下我们这个dp[i][j]表示的是传了i轮第j个同学路径数之和,我们这先考虑1人没有传也算是一种情况,然后针对不同的j有可能的几种情况就是当我是第一个时
那么就可以是第二个和最后一个传给我,我是最后一个时可以是第一个和n-1个传给我,当我在中间时就可以是左右两边的传给我那么我们可以写出这样的递推式
#include <bits/stdc++.h>
using namespace std;
int dp[31][31], m, n;
int main()
{
cin >> n >> m;
dp[0][1] = 1;
for (int i = 1; i <= m; i++)
{
for (int j = 1; j <= n; j++)
{
if (j == 1)//第一个
dp[i][j] = dp[i - 1][n] + dp[i - 1][2];
else if (j == n)//最后一个
dp[i][j] = dp[i - 1][1] + dp[i - 1][n - 1];
else//中间的
dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j + 1];
}
}
cout << dp[m][1] << endl;
return 0;
}
然后就ac了,然后尝试将代码简化,我们中间的if语句是真的需要吗?我们只是为了不越界然后就有了以下代码
#include <bits/stdc++.h>
using namespace std;
int dp[31][31];
int main()
{
int n,m;
cin>>n>>m;
dp[0][0]=1;//意思是一样的
for(int i=1;i<=m;i++)
{
for(int j=0;j<n;j++)//必须成从0开始表示的一样
//只是为了完成一个环的取模
{
dp[i][j]=dp[i-1][(j-1+n)%n]+dp[i-1][(j+1)%n];
}
}
cout<<dp[m][0];//表示传了m轮传加1号的方式
return 0;
}