CodeVs 1148 传球游戏
2014-10-04 11:55
225 查看
CodeVs 1148 传球游戏
解题报告
by MPS
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
题目描述 Description
上体育课的时候,小蛮的老师经常带着同学们一起做游戏。这次,老师带着同学们一起做传球游戏。
游戏规则是这样的:n个同学站成一个圆圈,其中的一个同学手里拿着一个球,当老师吹哨子时开始传球,每个同学可以把球传给自己左右的两个同学中的一个(左右任意),当老师再次吹哨子时,传球停止,此时,拿着球没传出去的那个同学就是败者,要给大家表演一个节目。
聪明的小蛮提出一个有趣的问题:有多少种不同的传球方法可以使得从小蛮手里开始传的球,传了m次以后,又回到小蛮手里。两种传球的方法被视作不同的方法,当且仅当这两种方法中,接到球的同学按接球顺序组成的序列是不同的。比如有3个同学1号、2号、3号,并假设小蛮为1号,球传了3次回到小蛮手里的方式有1->2->3->1和1->3->2->1,共2种。
输入描述 Input Description
共一行,有两个用空格隔开的整数n,m(3<=n<=30,1<=m<=30)。
输出描述 Output Description
共一行,有一个整数,表示符合题意的方法数。
样例输入 Sample Input
3 3
样例输出 Sample Output
2
数据范围及提示 Data Size & Hint
40%的数据满足:3<=n<=30,1<=m<=20
100%的数据满足:3<=n<=30,1<=m<=30
分析:
此题可以有两种解法:
①搜索——优化>③记忆化搜索
②动态规划
①搜索:
我们的阶段是每次的传球,很显然,状态为i,j //i表示当前传到第i个人手里,j表示已经传了j次
边界条件是:if(j==m) (m为输入的第二个数)
还有就是,由于是环形的,所以要特别注意i的变化,如果为0则改为n,如果为n+1,则改为1
每一次的决策就是dfs(i+1,j+1)和dfs(i-1,j+1)
然后在边界条件下统计:
if(j==m){
if(i==1)//传回到小蛮手里
ans++;
return;
}
由于决策是2种,故时间复杂度为O(2^n)
显然是不能AC的,那么,耗时间的地方在哪呢?很明显,我们发现决策中存在大量重叠子问题,那么我们可以改为记忆化搜索
代码读者自行思考(本文着重点不在这)
②动态规划
每一次传球为阶段,状态为f(i,j)表示传了j次到第i个人的方案数
决策是传左边还是右边
转移方程为f[i][j]=f[(i-1+n)%n][j-1]+f[(i+1)%n][j-1] (0<=i<n,1<=j<=k)
边界条件是 f[0][0]=1;
时间复杂度O(n^2)
解题报告
by MPS
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
题目描述 Description
上体育课的时候,小蛮的老师经常带着同学们一起做游戏。这次,老师带着同学们一起做传球游戏。
游戏规则是这样的:n个同学站成一个圆圈,其中的一个同学手里拿着一个球,当老师吹哨子时开始传球,每个同学可以把球传给自己左右的两个同学中的一个(左右任意),当老师再次吹哨子时,传球停止,此时,拿着球没传出去的那个同学就是败者,要给大家表演一个节目。
聪明的小蛮提出一个有趣的问题:有多少种不同的传球方法可以使得从小蛮手里开始传的球,传了m次以后,又回到小蛮手里。两种传球的方法被视作不同的方法,当且仅当这两种方法中,接到球的同学按接球顺序组成的序列是不同的。比如有3个同学1号、2号、3号,并假设小蛮为1号,球传了3次回到小蛮手里的方式有1->2->3->1和1->3->2->1,共2种。
输入描述 Input Description
共一行,有两个用空格隔开的整数n,m(3<=n<=30,1<=m<=30)。
输出描述 Output Description
共一行,有一个整数,表示符合题意的方法数。
样例输入 Sample Input
3 3
样例输出 Sample Output
2
数据范围及提示 Data Size & Hint
40%的数据满足:3<=n<=30,1<=m<=20
100%的数据满足:3<=n<=30,1<=m<=30
分析:
此题可以有两种解法:
①搜索——优化>③记忆化搜索
②动态规划
①搜索:
我们的阶段是每次的传球,很显然,状态为i,j //i表示当前传到第i个人手里,j表示已经传了j次
边界条件是:if(j==m) (m为输入的第二个数)
还有就是,由于是环形的,所以要特别注意i的变化,如果为0则改为n,如果为n+1,则改为1
每一次的决策就是dfs(i+1,j+1)和dfs(i-1,j+1)
然后在边界条件下统计:
if(j==m){
if(i==1)//传回到小蛮手里
ans++;
return;
}
由于决策是2种,故时间复杂度为O(2^n)
显然是不能AC的,那么,耗时间的地方在哪呢?很明显,我们发现决策中存在大量重叠子问题,那么我们可以改为记忆化搜索
代码读者自行思考(本文着重点不在这)
②动态规划
每一次传球为阶段,状态为f(i,j)表示传了j次到第i个人的方案数
决策是传左边还是右边
转移方程为f[i][j]=f[(i-1+n)%n][j-1]+f[(i+1)%n][j-1] (0<=i<n,1<=j<=k)
边界条件是 f[0][0]=1;
时间复杂度O(n^2)
#include <iostream> using namespace std; const int MaxN=1001; int n,m; long long f[MaxN][MaxN]; void init(){ freopen("ball.in","r",stdin); freopen("ball.out","w",stdout); cin>>n>>m; f[0][0]=1; } long long dp(){ int i,j; for(j=1;j<=m;j++) for(i=0;i<n;i++) f[i][j]=f[(i-1+n)%n][j-1]+f[(i+1)%n][j-1]; return f[0][m]; } int main(){ init(); cout<<dp(); return 0; }---------------------------------------------------------------------------------------------------------------------------------------------------
相关文章推荐
- Codevs 1148 == 洛谷 P1057 传球游戏
- Codevs 1148 == 洛谷 P1057 传球游戏
- Mayan游戏 (codevs 1136)题解
- codevs 1052 地鼠游戏 堆优化贪心 解题报告
- Codevs 1358 棋盘游戏
- 【codevs1033】蚯蚓的游戏问题
- 国王游戏(codevs 1198)
- 接龙游戏 [Codevs 1051]
- 【基础练习】【高速幂】codevs3285 转圈游戏题解
- CODEVS_1033 蚯蚓的游戏问题 网络流 最小费用流 拆点
- CodeVS1052 地鼠游戏 解题报告【背包型DP】
- CODE[VS] 1198【NOIP2012】 国王游戏(贪心
- code[vs] 1166矩阵取数游戏 (只是框架,未进行高精度)
- 【区间DP+高精】codevs1166 矩阵取数游戏题解
- codevs1166 矩阵取数游戏
- 【基础练习】【模拟】codevs1704 卡片游戏题解
- Codevs 1051 接龙游戏
- codevs1052 地鼠游戏 贪心
- codevs1198 国王游戏
- CODEVS 3285 转圈游戏