2016年第七届蓝桥杯 - 国赛 - Java大学C组 - I. 路径之谜
路徑之謎
小明冒充X星球的騎士,進入了一個奇怪的城堡。
城堡里邊什么都沒有,只有方形石頭鋪成的地面。
假設城堡地面是 n x n 個方格?!救鐖D1.png】所示。
按習俗,騎士要從西北角走到東南角。
可以橫向或縱向移動,但不能斜著走,也不能跳躍。
每走到一個新方格,就要向正北方和正西方各射一箭。
(城堡的西墻和北墻內各有 n 個靶子)
同一個方格只允許經過一次。但不必做完所有的方格。
如果只給出靶子上箭的數目,你能推斷出騎士的行走路線嗎?
有時是可以的,比如圖1.png中的例子。
本題的要求就是已知箭靶數字,求騎士的行走路徑(測試數據保證路徑唯一)
輸入:
第一行一個整數N(0<N<20),表示地面有 N x N 個方格
第二行N個整數,空格分開,表示北邊的箭靶上的數字(自西向東)
第三行N個整數,空格分開,表示西邊的箭靶上的數字(自北向南)
輸出:
一行若干個整數,表示騎士路徑。
為了方便表示,我們約定每個小格子用一個數字代表,從西北角開始編號: 0,1,2,3…
比如,圖1.png中的方塊編號為:
0 1 2 3
4 5 6 7
8 9 10 11
12 13 14 15
示例:
用戶輸入:
4
2 4 3 4
4 3 3 3
程序應該輸出:
0 4 5 1 2 3 7 11 10 9 13 14 15
資源約定:
峰值內存消耗 < 256M
CPU消耗 < 1000ms
請嚴格按要求輸出,不要畫蛇添足地打印類似:“請您輸入…” 的多余內容。
所有代碼放在同一個源文件中,調試通過后,拷貝提交該源碼。
注意:不要使用package語句。不要使用jdk1.7及以上版本的特性。
注意:主類的名字必須是:Main,否則按無效代碼處理。
Ideas
這道題類似一個迷宮問題,迷宮問題想搜索,最優問題想廣搜,不然想深搜。
對于深搜函數DFS來說,肯定需要傳入一個位置坐標x和y,然后這道題還需要輸出騎士走的路徑,所以在最后找到一個符合條件的路徑之后還要輸出。
之后就是正常的DFS套路了,四個方向都走一走,保證不要越界,并且還需要一個visit數組表示某個位置是否被訪問過,最后從西北角搜索到東南角就OK了。
當然這道題還需要確保箭靶數字符合要求,所以我們其實可以利用這個條件做一個剪枝,當我們走到一個位置之后,其實可以把對應位置的兩個箭靶數字減去1,如果某一個位置箭靶數字剪成了負數,說明白不符合條件,就可以直接return。
Code
C++
#include <iostream> #include <vector>using namespace std;struct Node {bool flag;int x, y; };Node map[20][20]; vector<int> road; int N, X[20], Y[20], sum; int dir[4][2] = {{0, 1},{1, 0},{-1, 0},{0, -1}};bool dfs(int x, int y) {if (x == N - 1 && y == N - 1) {for (int i = 0; i < N; i++) {if (X[i] || Y[i] || sum)return false;road.push_back(x * N + y);return true;}}road.push_back(x * N + y);map[x][y].flag = true;for (int i = 0; i < 4; i++) {int tx = x + dir[i][0];int ty = y + dir[i][1];if (tx < 0 || tx > (N - 1) || ty < 0 || ty > (N - 1))continue;if (!map[tx][ty].flag && (X[tx] > 0 && Y[ty] > 0)) {X[tx]--;Y[ty]--;sum -= 2;if (dfs(tx, ty))return true;else {X[tx]++;Y[ty]++;sum += 2;}}}map[x][y].flag = false;road.erase(road.begin() + road.size() - 1);return false; }int main() {cin >> N;for (int i = 0; i < N; i++){cin >> Y[i];sum += Y[i];}for (int i = 0; i < N; i++) {cin >> X[i];sum += X[i];}for (int i = 0; i < N; i++) {for (int j = 0; j < N; j++) {map[i][j].flag = false;map[i][j].x = i;map[i][j].y = j;}}X[0]--;Y[0]--;sum -= 2;dfs(0, 0);for (int i = 0; i < road.size(); i++)cout << road[i] << ' ';return 0; }Python
def dfs(r, c):"""Args:r: 當前搜索行c: 當前搜索列Returns: Bool值,表示是否找到了一條符合條件路徑"""if r == n - 1 and c == n - 1:if sum(north_target) > 0 or sum(west_target) > 0: # 如果最后還有箭靶上面的數目不為零,也不符合要求return Falsepath.append(r * n + c)print(' '.join(map(str, path)))return Truepath.append(r * n + c)direction = [(0, 1), (1, 0), (0, -1), (-1, 0)]for dr, dc in direction:nr, nc = r + dr, c + dc # 下一個搜索位置的行、列# 保證下一個搜索的位置符合要求if -1 < nr < n and -1 < nc < n and not visit[nr][nc] and north_target[nc] > 0 and west_target[nr] > 0:visit[nr][nc] = Truenorth_target[nc] -= 1west_target[nr] -= 1if dfs(nr, nc):return Trueelse:visit[nr][nc] = Falsenorth_target[nc] += 1west_target[nr] += 1path.pop()return Falseif __name__ == '__main__':n = int(input())north_target = list(map(int, input().split()))west_target = list(map(int, input().split()))path = []visit = [[False] * n for _ in range(n)]visit[0][0] = Truenorth_target[0] -= 1west_target[0] -= 1dfs(0, 0)在線評測:https://www.acwing.com/problem/content/description/3193/
這道題至今只有1個人AC了,上面的代碼應該只能拿70分,求AC大佬分享。
總結
以上是生活随笔為你收集整理的2016年第七届蓝桥杯 - 国赛 - Java大学C组 - I. 路径之谜的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2015年第六届蓝桥杯C/C++ A组国
- 下一篇: 2018年第九届蓝桥杯C/C++ A组国