一、题意分析
总结题中的骨牌特性:两点、双向,你会想到什么?
请思考 3 秒钟
没错,答案就是无向图
我们以一组输入为例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| 10 13 1 0 6 4 0 4 0 4 0 3 5 1 6 0 0 3 1 6 2 4 6 6 6 0 1 6 3 5 4 3
|
由以上的数据我们可以做出一个无向图(见右图)
图中的红色箭头分别为开始和结束的骨牌($(1, 0)、(6, 4)$)
所以,题目就转化为能否找到一条从 $0$ 到 $6$ 的长度为 $10$ 的路线
二、思路总结
显然,对于本题来说,深度优先搜索是最好的选择。那么,什么是深度优先搜索?
深度优先搜索 (DFS) 全称是 Depth First Search,是一种用于遍历或搜索树或图的算法。所谓深度优先,就是说每次都尝试向更深的节点走。
—— OI Wiki
要想正确地用递归写出一段 DFS 的代码,我们需要知道以下信息:
- 每次递归需要做什么?
- 递归的结束条件是什么?
- DFS 的回溯条件是什么?
请仔细思考一下,思考完成后点击左边的箭头展开答案
> 每次递归获取一个编号并寻找包含这个编号的骨牌,再以该骨牌的另一个编号进行下一次递归
> 距离达标且当前编号等于结束编号
> 距离达标但当前编号不等于结束编号
三、AC 代码
C++
C++ 的码风略差,将就着看看吧
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| #include <bits/stdc++.h>
using namespace std;
struct card { int lst, nxt; bool flag = false; } start, ed, cur_card, cardList[1000000]; int n, m; bool solved;
void find_next(int card, int distance) { if (distance == n and card == ed.lst) { solved = true; return; } if (distance >= n) return; for (int c = 0; c < m; c++) { cur_card = cardList[c]; if (cur_card.lst == card and !cur_card.flag) { cardList[c].flag = true; find_next(cur_card.nxt, distance + 1); cardList[c].flag = false; } else if (cur_card.nxt == card and !cur_card.flag) { cardList[c].flag = true; find_next(cur_card.lst, distance + 1); cardList[c].flag = false; } }
}
int main() { while (true) { cin >> n; if (n == 0) return 0; cin >> m; cin >> start.lst >> start.nxt; cin >> ed.lst >> ed.nxt; for (int i = 0; i < m; i++) cin >> cardList[i].lst >> cardList[i].nxt; solved = false; find_next(start.nxt, 0); if (solved) cout << "YES" << endl; else cout << "NO" << endl; } }
|
Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| class CLS_card(object): def __init__(self, lst, nxt): self.lst = lst self.nxt = nxt self.flag = False
def find_next(card, distance): global solved if distance == n and card == end.lst: solved = True return if distance >= n: return for c in cardList: if c.lst == card and c.flag == False: c.flag = True find_next(c.nxt, distance + 1) c.flag = False elif c.nxt == card and c.flag == False: c.flag = True find_next(c.lst, distance + 1) c.flag = False
while True: n = eval(input()) if n == 0: break m = eval(input()) inp = input().split() start = CLS_card(int(inp[0]), int(inp[1])) inp = input().split() end = CLS_card(int(inp[0]), int(inp[1])) cardList = [] for i in range(m): inp = input().split() cardList.append(CLS_card(int(inp[0]), int(inp[1]))) solved = False find_next(start.nxt, 0) if solved: print('YES') else: print('NO')
|