啊哈,我又来了
今天就不水博客了,就說一說洛谷上的一道好題吧!
https://www.luogu.org/problemnew/show/P1057
題目描述
上體育課的時候,小蠻的老師經常帶著同學們一起做游戲。這次,老師帶著同學們一起做傳球游戲。
游戲規則是這樣的:n個同學站成一個圓圈,其中的一個同學手里拿著一個球,當老師吹哨子時開始傳球,每個同學可以把球傳給自己左右的兩個同學中的一個(左右任意),當老師再次吹哨子時,
傳球停止,此時,拿著球沒有傳出去的那個同學就是敗者,要給大家表演一個節目。
聰明的小蠻提出一個有趣的問題:有多少種不同的傳球方法可以使得從小蠻手里開始傳的球,傳了m次以后,又回到小蠻手里。兩種傳球方法被視作不同的方法,當且僅當這兩種方法中,接到球的同學按接球順序組成的序列是不同的。
比如有三個同學1號、2號、3號,并假設小蠻為1號,球傳了3次回到小蠻手里的方式有1->2->3->1和1->3->2->1,共2種。
輸入格式:
一行,有兩個用空格隔開的整數n,m,?n,m(3≤n≤30,1≤m≤30)。
輸出格式:
1個整數,表示符合題意的方法數。
題解分界線
這道題是一道遞推的題,并且我認為能用暴力枚舉加上剪枝做出來,不過這就“委屈”了這道好題了,
所以后面的解法就是從遞推的角度出發的,
怎么遞推呢?
額......
其實想一想還是有答案的,我是從分解問題的角度出發的,遞推往往符合從簡到繁的過程,所以一定有一種方式能夠使得傳球的方法有簡一次次遞推出來。
首先我們就可以認為對于一種情況,從i傳到j并且傳了k次,我們用dt[i][j][k]來表示,則i傳到j用了m次這個狀態就可以從i到j-1傳了k-1次與從i傳到j+1傳了k-1次相加得到,
即dt[i][j][k-1] = dt[i][j-1][k-1] + dt[i][j+1][k-1]
有了這個,這道題就沒什么難度了,后面就注意一下初始化以及環的特點(因為是站成一個圓圈傳球的嘛!~)
下面就是代碼:
//P1057 #include <iostream> using namespace std; const int Max = 35; int dt[Max][Max][Max]; //dt[i][j][k]表示從i走到j用了k次一共有多少種方法 //dt[i][j][k] = dt[i][j-1][k-1] + dt[i][j+1][k-1] //處理環的特點 int main() {int n, m; cin >> n >> m; for (int i = 0; i < n; ++i) dt[i][(i+1)%n][1] = dt[i][(i+n-1)%n][1] = 1;for (int k = 2; k <= m; ++k) for (int i = 0; i < n; ++i) for (int j = 0; j < n; ++j) dt[i][j][k] = dt[i][(j+n-1)%n][k-1] + dt[i][(j+1)%n][k-1]; cout << dt[1][1][m]; return 0; }非常的簡單吧!哈哈。
總結:我們面對問題時一定要有解決問題的基本引導思路,遞推的題困難就在如何定義狀態并且能夠將狀態“傳遞”下去,多練會有長進的。?
就說這么多了,寫作業去了,每天都要努力哦!
1/2 clear(胡寫的)
轉載于:https://www.cnblogs.com/yifeiWa/p/10638890.html
總結
- 上一篇: Java-反射浅谈
- 下一篇: 针对【H-2017年信息基础班(周一班)