洛谷P1057 传球游戏【dp】

题目https://www.luogu.org/problemnew/show/P1057

题意:

n个人围成一个圈,传球只能传给左边或是右边。

从第一个人开始传起,经过m次之后回到第一个人的传球方案有多少种。

思路:

发现有的时候dp的转移方程可以通过写递归得到。把递归给变成dp

用$dp[i][j]$表示第$j$号开始传$i$次回到$j$的方案数。很容易想到,第$i$次回到$j$时,一定是$j-1$或是$j+1$传回来的。

所以可以得到$dp[i][j] = dp[i-1][j-1]+dp[i-1][j+1]$

初始时是$dp[0][0] = 1$,终态是$dp[m][0]$

要注意因为是一个圈,所以我们用%来处理。为避免负数,$-1$的时候要$+n$

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 #include<map>
 4 #include<set>
 5 #include<iostream>
 6 #include<cstring>
 7 #include<algorithm>
 8 #include<vector>
 9 #include<cmath> 
10 #include<queue>
11 
12 #define inf 0x7f7f7f7f
13 using namespace std;
14 typedef long long LL;
15 typedef pair<int, int> pr;
16 
17 int n, m;
18 
19 int dp[35][35];
20 //dp[i][j]表示传i次回到j的方案数
21 //dp[i][j] = dp[i-1][j-1] + dp[i-1][j+1] 
22 
23 //int dfs(int x, int id)
24 //{
25 //    if(dp[x][id])return dp[x][id];
26 //    if(x == 0){
27 //        return 1;
28 //    }
29 //    int ans = 0;
30 //    ans += dfs(x - 1, (id + 1) % n);
31 //    ans += dfs(x - 1, (id - 1) % n);
32 //    dp[x][id] = ans;
33 //    return ans;
34 //}
35 
36  
37 int main()
38 {
39     scanf("%d%d", &n, &m);
40     dp[0][0] = 1;
41     for(int i = 1; i <= m; i++){
42         for(int j = 0; j < n; j++){
43             dp[i][j] = dp[i - 1][(j - 1 + n) % n] + dp[i - 1][(j + 1) % n];
44         }
45     }
46     printf("%d\n", dp[m][0]);
47     
48     return 0;
49 }

 

posted @ 2019-02-15 17:07  wyboooo  阅读(124)  评论(0编辑  收藏  举报