UVa439(騎士的移動)
阿新 • • 發佈:2020-08-10
這道題主要是寫一個圖的遍歷。因為題目中要求是最短路徑,所以採用的是寬度優先遍歷。本來是想縮短執行時間而採用頭尾同時使用bfs演算法,但奈何個人水平有限而未能實現。所以本題程式碼中使用就是最直接的bfs演算法。由於寫這段程式碼時比較匆忙,所以程式碼應該還有較大的優化空間。
1 #include <bits/stdc++.h>
2
3 using namespace std;
4
5 /*******************
6 UVa439 騎士的移動
7 *******************/
8
9 struct Node{
10 // x1列 x2行 k是走到這個點需要的步數
11 int x1, x2, k;
12 Node(int x = 0, int y = 0, int weight = 0):x1(x), x2(y), k(weight){}
13 bool equal(Node& n){
14 return (x1 == n.x1 && x2 == n.x2);
15 }
16 };
17
18 int k = 0;
19 int buf[7][7];
20 queue<Node> q1;
21
22 int char_to_int(char ch){
23 return ch-96;
24 }
25
26 //尋找下一個位置並且將結構體入隊並且修改棋盤訪問狀態
27 int next(Node& n, Node& end){
28 if(n.x1 + 2 <= 8 && n.x2 + 1 <= 8 && !buf[n.x2][n.x1 + 1]){
29 Node n1(n.x1 + 2, n.x2 + 1, n.k+1);
30 if(n1.equal(end)){
31 printf(" %d", n1.k);
32 return 1;
33 }else{
34 q1.push(n1);
35 buf[n1.x2-1][n1.x1-1] = 1;
36 }
37 }
38 if(n.x1 + 1 <= 8 && n.x2 + 2 <= 8 && !buf[n.x2 + 1][n.x1]){
39 Node n1(n.x1 + 1, n.x2 + 2, n.k+1);
40 if(n1.equal(end)){
41 printf("%d", n1.k);
42 return 1;
43 }else{
44 q1.push(n1);
45 buf[n1.x2-1][n1.x1-1] = 1;
46 }
47 }
48 if(n.x1 - 1 >= 1 && n.x2 + 2 <= 8 && !buf[n.x2 + 1][n.x1 - 2]){
49 Node n1(n.x1 - 1, n.x2 + 2, n.k+1);
50 if(n1.equal(end)){
51 printf("%d", n1.k);
52 return 1;
53 }else{
54 q1.push(n1);
55 buf[n1.x2-1][n1.x1-1] = 1;
56 }
57 }
58 if(n.x1 - 2 >= 1 && n.x2 + 1 <= 8 && !buf[n.x2][n.x1 - 3]){
59 Node n1(n.x1 - 2, n.x2 + 1, n.k+1);
60 if(n1.equal(end)){
61 printf("%d", n1.k);
62 return 1;
63 }else{
64 q1.push(n1);
65 buf[n1.x2-1][n1.x1-1] = 1;
66 }
67 }
68 if(n.x1 + 1 <= 8 && n.x2 - 2 >= 1 && !buf[n.x2 - 3][n.x1]){
69 Node n1(n.x1 + 1, n.x2 - 2, n.k+1);
70 if(n1.equal(end)){
71 printf("%d", n1.k);
72 return 1;
73 }else{
74 q1.push(n1);
75 buf[n1.x2-1][n1.x1-1] = 1;
76 }
77 }
78 if(n.x1 + 2 <= 8 && n.x2 - 1 >= 1 && !buf[n.x2 - 2][n.x1 + 1]){
79 Node n1(n.x1 + 2, n.x2 - 1, n.k+1);
80 if(n1.equal(end)){
81 printf("%d", n1.k);
82 return 1;
83 }else{
84 q1.push(n1);
85 buf[n1.x2-1][n1.x1-1] = 1;
86 }
87 }
88 if(n.x1 - 1 >= 1 && n.x2 - 2 >= 1 && !buf[n.x2 -3][n.x1 - 2]){
89 Node n1(n.x1 - 1, n.x2 - 2, n.k+1);
90 if(n1.equal(end)){
91 printf("%d", n1.k);
92 return 1;
93 }else{
94 q1.push(n1);
95 buf[n1.x2-1][n1.x1-1] = 1;
96 }
97 }
98 if(n.x1 - 2 >= 1 && n.x2 - 1 >= 1 && !buf[n.x2 - 2][n.x1 - 3]){
99 Node n1(n.x1 - 2, n.x2 - 1, n.k+1);
100 if(n1.equal(end)){
101 printf("%d", n1.k);
102 return 1;
103 }else{
104 q1.push(n1);
105 buf[n1.x2-1][n1.x1-1] = 1;
106 }
107 }
108 return 0;
109 }
110
111 void solve(Node n1, Node n2){
112
113 for(;;){
114 //尋找下一個位置
115 if(next(n1, n2)){
116 break;
117 }else{
118 n1 = q1.front(); q1.pop();
119 continue;
120 }
121 }
122 return;
123 }
124
125 int main()
126 {
127 char x = 0;
128 int y = 0;
129 memset(buf, 0, sizeof(buf));
130
131 //輸入起使位置
132 cin >> x;
133 cin >> y;
134 Node start = Node(char_to_int(x), y, 0);
135 buf[y-1][char_to_int(x)-1] = 1;
136 //輸入終止位置
137 cin >> x;
138 cin >> y;
139 Node end = Node(char_to_int(x), y, 0);
140 if(start.equal(end)){
141 printf("0");
142 return 0;
143 }
144 solve(start, end);
145 return 0;
146 }
這段程式碼的主要思路就是使用bfs演算法遍歷圖,同時記錄走到該點需要的最短步數,當遍歷過程中發現遍歷到了終點,就列印步數,並且退出程式。整段程式碼並不複雜,其中最長的next()函式反而是最直觀的。
執行結果如下:
a1
b2
4