本著刷一刷noip真題做了這道,寫篇題解加深印象。
傳送門
題面總的來說就是n個人圍城個圈,每次傳球只能傳給左邊或右邊,設從1號位發球,求m步傳回1號位的方案數。
從1號位開始搜,每次向左右兩邊擴充套件,m步時落在1號位ans++。其中1和n的情況需要判斷一下。
#include
#include
using
namespace std;
const
int maxn =35;
int n, m, ans;
intdfs
(int step,
int cnt)
if(step ==1)
if(step == n)
return
dfs(step -
1, cnt +1)
+dfs
(step +
1, cnt +1)
;}intmain()
但這樣顯然不行,o(2
n)
o(2^n)
o(2n
)的時間複雜度不允許啊!
不難發現會有同種狀態搜尋多次的情況,這就使得複雜度蹭蹭的加。所以我們可以將每種狀態存進乙個二維陣列。
#include
#include
using
namespace std;
const
int maxn =35;
int n, m, ans;
int dp[maxn]
[maxn]=;
intdfs
(int step,
int cnt)
if(dp[step]
[cnt]
)return dp[step]
[cnt];if
(step ==1)
if(step == n)
return dp[step]
[cnt]
=dfs
(step -
1, cnt +1)
+dfs
(step +
1, cnt +1)
;}intmain()
但這依然有乙個測試點過不了。
簡單分析一下,可以推出當n為偶數,m為奇數時是無解的
因為能傳回1號位只有兩種情況:
傳出去,再原路傳回來(可能會相互傳):
若經過了x個人,則一共所用2*x步
傳出去,順著走完每個人回來:
若總人數為偶數,則步數為偶數;(因為互相傳每次會 + 2,偶數+2總是偶數)
反之為奇數。(奇數+2總是奇數)
綜上作述:當步數為奇數且人數為偶數時時,是無解的。
#include
#include
using
namespace std;
const
int maxn =35;
int n, m, ans;
int dp[maxn]
[maxn]=;
intdfs
(int step,
int cnt)
if(dp[step]
[cnt]
)return dp[step]
[cnt];if
(step ==1)
if(step == n)
return dp[step]
[cnt]
=dfs
(step -
1, cnt +1)
+dfs
(step +
1, cnt +1)
;}intmain()
ans =
dfs(1,
0);printf
("%d"
, ans)
;return0;
}
其實dp的本質就是記憶化搜尋。
d pi
,j
dp_dp
i,j
表示用 i 步走到 j 號位的總方案數。
很容易推出轉移方程:dp[
i,j]
=∑j=
1ndp
[i−1
,j
]dp[i,j]=\sum_^dp[i-1,j]
dp[i,j
]=∑j
=1n
dp[i
−1,j
]。邊界是dp[
0,1]
=1
dp[0, 1]=1
dp[0,1
]=1。
#include
#include
using
namespace std;
const
int maxn =35;
int n, m;
int dp[maxn]
[maxn]
;int
main()
}printf
("%d"
, dp[m][1
]);return0;
}
noip2008 傳球遊戲
上體育課的時候,小蠻的老師經常帶著同學們一起做遊戲。這次,老師帶著同學們一起做傳球遊戲。遊戲規則是這樣的 n個同學站成乙個圓圈,其中的乙個同學手裡拿著乙個球,當老師吹哨子時開始傳球,每個同學可以把球傳給自己左右的兩個同學中的乙個 左右任意 當老師再次吹哨子時,傳球停止,此時,拿著球沒傳出去的那個同學...
NOIP 2008 傳球遊戲
洛谷傳送門 jdoj傳送門 上體育課的時候,小蠻的老師經常帶著同學們一起做遊戲。這次,老師帶著同學們一起做傳球遊戲。遊戲規則是這樣的 n個同學站成乙個圓圈,其中的乙個同學手裡拿著乙個球,當老師吹哨子時開始傳球,每個同學可以把球傳給自己左右的兩個同學中的乙個 左右任意 當老師再次吹哨子時,傳球停止,此...
NOIP2008 傳球遊戲
輸入檔案 ballg.in輸出檔案 ballg.out簡單對比 時間限制 1 s 記憶體限制 50 mb 問題描述 上體育課的時候,小蠻的老師經常帶著同學們一起做遊戲。這次,老師帶著同學們一起做傳球遊戲。遊戲規則是這樣的 n個同學站成乙個圓圈,其中的乙個同學手裡拿著乙個球,當老師吹哨子時開始傳球,每...