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");
}
posted @ 2020-10-01 14:48  Dazzling!  阅读(144)  评论(0编辑  收藏  举报