文章目錄
1. 題目描述
1.1. Limit
Time Limit: 1000 ms
Memory Limit: 131072 kB
1.2. Problem Description
貝倫卡斯泰露,某種程度上也可以稱爲古手梨花,能夠創造機率近乎爲0的奇蹟,通過無限輪迴成功打破了世界線收束理論。和某科學者不同,貝倫並不在意世界線收束的那套理論,作爲奇蹟之魔女,貝倫的愛好只在於品茶。作爲品茶的消遣,貝倫正在解一道簡單的謎題。
給出一個長度爲n的數列 ,問是否能將這個數列分解爲兩個長度爲 的子序列,滿足
- 兩個子序列不互相重疊。
- 兩個子序列中的數要完全一樣, ,。
1.3. Input
第一行,一個正整數 ,表示數據組數。
接下來 組數據,每組數據的第一行,一個正整數 ,第二行 個正整數 。
1.4. Output
每組數據輸出一行,如果可以完成,輸出Frederica Bernkastel,否則輸出Furude Rika。
1.5. Sample Input
3
4
1 1 2 2
6
1 2 3 4 5 6
4
1 2 2 1
1.6. Sample Output
Frederica Bernkastel
Furude Rika
Furude Rika
1.7. Source
2. 解讀
DFS
維護兩個數組 和 , 在每遇到一個匹配的元素 時,會進入分岔點,如果該元素 進入隊列 後能夠搜索完全部元素,則搜索完成。
如果 中的元素數列超過所有元素數列 的一半,即 ,則回退到上一步,讓元素進入。
重複上述步驟即能遍歷所有情況。
比如如下測試用例。
1
6
1 1 2 1 1 2
序號 | 入隊元素 | 備註 | ||
---|---|---|---|---|
1 | 1 | 1 | 初始化 | |
2 | 1 | 1 | 1 | 入隊 B |
3 | 1 2 | 1 | 2 | 入隊 A |
4 | 1 2 1 | 1 | 1 | 入隊 A |
5 | 1 2 1 1 | 1 | 1 | 隊A元素4 > 3 |
6 | 1 | 回退 | ||
7 | 1 1 | 1 | 入隊 A | |
8 | 1 1 2 | 2 | 入隊 A | |
9 | 1 1 2 | 1 | 1 | 入隊B |
10 | 1 1 2 | 1 1 | 1 | 入隊B |
11 | 1 1 2 | 1 1 2 | 2 | 入隊B |
12 | 1 1 2 | 1 1 2 | 搜索完成 |
3. 代碼
#include <iostream>
using namespace std;
int list[41], listA[41], listB[41], t, n;
//i,j分別表示listA[],listB[]中元素個數,id表示當前匹配元素下標
bool dfs(int i, int j, int id)
{
if (i > n / 2 || j > n / 2) {
// 若子序列中元素個數大於總元素個數的一半,停止搜索
return 0;
}
if (id > n) {
// 若已搜索完全部元素,搜索完成
return 1;
}
//當前元素匹配,加入到listB[]
if (list[id] == listA[j + 1]) {
listB[j + 1] = list[id];
// listB長度加一,繼續遞歸
if (dfs(i, j + 1, id + 1)) {
// 若搜索完成,結束搜索
return 1;
}
}
//即使相等也加入listA[]或者不相等加入到listA[]
listA[i + 1] = list[id];
// listA長度加一,遞歸
return dfs(i + 1, j, id + 1);
}
int main()
{
cin >> t;
while (t--) {
cin >> n;
for (int i = 1; i <= n; i++)
cin >> list[i];
listA[1] = list[1];
puts(dfs(1, 0, 2) ? "Frederica Bernkastel" : "Furude Rika");
}
return 0;
}
注:代碼參考自v5zsq 的CSDN博客
聯繫郵箱:[email protected]
Github:https://github.com/CurrenWong
歡迎轉載/Star/Fork,有問題歡迎通過郵箱交流。