P1057 传球游戏
递推计数,注意边界为\(1\)和\(n\)的时候特判一下
状态表示:\(f(i,j)\):传了\(i\)次球后,球在第\(j\)个人手中的方案数
状态转移:
- 填表法:\(f(i,j)=f(i-1,l)+f(i-1,r)\),\(l\)表示\(j\)左边的人,\(r\)表示\(j\)右边的人
- 刷表法:\(f(i+1,l)+=f(i,j),f(i+1,r)+=f(i,j)\)
填表法
const int N=35;
int f[N][N];
int n,m;
int main()
{
cin>>n>>m;
f[0][1]=1;
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
{
int l=(j-1>0?j-1:n),r=(j+1>n?1:j+1);
f[i][j]=f[i-1][l]+f[i-1][r];
}
cout<<f[m][1]<<endl;
//system("pause");
}
刷表法
const int N=35,M=35;
int f[M][N];
int n,m;
int main()
{
cin>>n>>m;
f[0][1]=1;
for(int i=0;i<m;i++)
for(int j=1;j<=n;j++)
{
int l=j-1>0?j-1:n,r=j+1>n?1:j+1;
f[i+1][l]+=f[i][j];
f[i+1][r]+=f[i][j];
}
cout<<f[m][1]<<endl;
//system("pause");
}
滚动数组优化:
const int N=35;
int f[2][N];
int n,m;
int main()
{
cin>>n>>m;
f[0][1]=1;
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
{
int l=(j-1>0?j-1:n),r=(j+1>n?1:j+1);
f[i&1][j]=f[i-1&1][l]+f[i-1&1][r];
}
cout<<f[m&1][1]<<endl;
//system("pause");
}