工作空閒之餘,蒜頭君經常帶着同事們做遊戲,最近蒜頭君發明了一個好玩的新遊戲:nn 位同事圍成一個圈,同事 A 手裏拿着一個兔妮妮的娃娃。蒜頭君喊遊戲開始,每位手裏拿着娃娃的同事可以選擇將娃娃傳給左邊或者右邊的同學,當蒜頭君喊遊戲結束時,停止傳娃娃。此時手裏拿着娃娃的同事即是敗者。
玩了幾輪之後,蒜頭君想到一個問題:有多少種不同的方法,使得從同事 A 開始傳娃娃,傳了 mm次之後又回到了同事 A 手裏。兩種方法,如果接娃娃的同事不同,或者接娃娃的順序不同均視爲不同的方法。例如 1->2->3->11−>2−>3−>1 和 1->3->2->11−>3−>2−>1 是兩種不同的方法。
輸入格式
輸入一行,輸入兩個整數 n,m(3 \leq n \leq 30,1 \leq m \leq 30)n,m(3≤n≤30,1≤m≤30),表示一共有 nn 位同事一起遊戲,一共傳 mm 次娃娃。
輸出格式
輸出一行,輸出一個整數,表示一共有多少種不同的傳娃娃方法。
樣例輸入
3 3
樣例輸出
2
/*
這道題算是道老題, 想想第一次做的時候, 好不容易想出來的,
當時也感覺真正的dp入門了.
現在做卻還是有一點波折.
首先是拆分過程, 定義子狀態:
從 A 開始傳, 第 m 次傳到 A , 那麼只能從 A 的左邊和右邊傳過去.
現在定義狀態 dp[m, 0] 爲傳了 m 次傳到 A 的方法數,
狀態轉移方程爲 dp[m, 0] = dp[m - 1, 1] + dp[m - 1, (0 - 1) % n]
dp[m - 1, 1] 表示 傳了 m - 1 次, 傳到 1 的方法數
dp[m - 1, (0 - 1) % n] 表示 傳了 m - 1 次, 傳到 (0 - 1) % n的方法數
取餘的目的是將這些人圍成一個環
*/
/*
這次做, 讓我知道通過狀態轉移方程的做法與記憶化搜索的時間有很大差異
以下兩個代碼爲第一次過的兩個代碼
*/
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn = 35;
int n, m;
ll dp[maxn][maxn];
ll search(int n_steps, int person);
int main()
{
// memset(dp, -1, sizeof(dp));
dp[0][0] = 1;
cin >> n >> m;
for(int i = 1; i <= m; ++i){
for(int j = 0; j < n; ++j){
dp[i][j] = dp[i - 1][(j + 1) % n] + dp[i - 1][(j + n - 1) % n];
}
}
cout << dp[m][0] << endl;
return 0;
}
ll search(int n_steps, int person)// TLE
{// 可能是無用的狀態有點多
if(dp[n_steps][person] != -1)
return dp[n_steps][person];
if(n_steps == 0){
if(person == 0)
return dp[0][0] = 1;
else
return dp[0][person] = 0;
}
return search(n_steps - 1, (person + 1) % n)
+ search(n_steps - 1, (person + n - 1) % n);
}
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int MAXN = 35;
int dp[MAXN][MAXN];
int N, M;
int rec(int m, int pos)
{
if(dp[m][pos] != -1)
return dp[m][pos];
int res;
if(m == 0 && pos == 1)
res = 1;
else if(m == 0)
res = 0;
else if(pos == 1)
res = rec(m - 1, 2) + rec(m - 1, N);
else if(pos == N)
res = rec(m - 1, 1) + rec(m - 1, N - 1);
else
res = rec(m - 1, pos - 1) + rec(m - 1, pos + 1);
return dp[m][pos] = res;
}
int main()
{
memset(dp, -1, sizeof(dp));
cin >> N >> M;
int ans = rec(M, 1);
cout << ans << endl;
return 0;
}
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
int n, m, dp[35][35];
memset(dp, 0, sizeof(dp));
cin >> n >> m;
dp [1][0] = dp[0][1] = dp[0][n + 1] = 1;
for(int i = 1; i <= m; ++i){
for(int pos = 1; pos <= n; ++pos){
dp[i][pos] = dp[i - 1][pos - 1] + dp[i - 1][pos + 1];
}
dp[i][n + 1] = dp[i][1];
dp[i][0] = dp[i][n];
}
cout << dp[m][1] << endl;
return 0;
}