P1057 [NOIP2008 普及组] 传球游戏

P1057 [NOIP2008 普及组] 传球游戏_第1张图片
P1057 [NOIP2008 普及组] 传球游戏_第2张图片
解题思路:
1.40分做法:采用dfs进行遍历,当满足传球次数达到m次的时候检验此时球在不在第一个同学手里。图示:
P1057 [NOIP2008 普及组] 传球游戏_第3张图片
如图可以深度优先遍历该树,如果发现次数等于m次,而且此时在0号同学身上,则路径+1,最后输出该结果就行,代码如下:

#include
using namespace std;
using gg=long long;
gg ni,mi;//几个人,传多少次球
gg res=0;
void dfs(gg start,gg current)
{
    if(current==mi&&start==0)
    {
        res+=1;
        return;
    }
    else if(current>mi)
    {
        return;
    }
    else
    {
        dfs((start+1+ni)%ni,current+1);//0号到1号手里
        dfs((start-1+ni)%ni,current+1);//0号到2号
    }

}
int main()
{
    cin>>ni>>mi;
    dfs(0,0);
    cout<<res<<endl;
}

当然这样会超时,采用动态规划就行优化

2.动态规划:上图从圈出红色的地方可以看到有重复计算的地方。于是构造一个数组dp[i][j],代码如下:

#include
using namespace std;
using gg=long long;
int dp[50][50];//dp[i][j]表示第i次传递到第j个同学手里的次数
int main()
{
    int ni,mi;
    cin>>ni>>mi;
    dp[0][0]=1;
    for(int i=1;i<=mi;i++)
    {
        for(int j=0;j<ni;j++)
        {
            int bj = (j-1+ni)%ni;
            int cj = (j+1+ni)%ni;
            dp[i][j]=dp[i-1][bj]+dp[i-1][cj];
        }
    }
    cout<<dp[mi][0]<<endl;
}

你可能感兴趣的:(洛谷,c++,c++)