UVa 10067 - Playing with Wheels

Contents

  1. 1. Problem
  2. 2. Solution
  3. 3. Code

Problem

題目網址
中文網址

給初始的數字,求出最少要轉動幾次才能達到目標的數字。
且中途不得出現禁止的數字。

Solution

做 BFS,每次增加的節點為將四個數字分別上下轉動,注意 0 <-> 9 的情形。
另外還有幾個特殊狀況:起點和終點相同、終點為禁止的數字。

Code

UVa 10067
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#include <cstdio>
#include <cstring>
#include <queue>
#define N 10000

inline int input()
{
/*int tmp[4];
scanf("%d%d%d%d", &tmp[0], &tmp[1], &tmp[2], &tmp[3]);
return tmp[3]*1000 + tmp[2]*100 + tmp[1]*10 + tmp[0];*/

int n = 0, k = 0;
char ch;
while (k < 4)
{
ch = getchar();
if (ch >= '0' && ch <= '9')
{
n = n * 10 + ch - '0';
++k;
}
}
return n;
}
int main()
{
//freopen("test.out", "w", stdout);
int T;
bool visited[N] = {};
int step[N] = {};
scanf("%d", &T);
while (T--)
{
int s, t, n;
s = input();
t = input();
scanf("%d", &n);

for (int i = 0; i < n; ++i)
visited[input()] = true;

if (s == t)
puts("0");
else if (visited[t])
puts("-1");
else
{
//BFS
std::queue<int> Q;
Q.push(s);
visited[s] = true;

while (!Q.empty())
{
int now = Q.front();
Q.pop();

for (int k = 1000, cpy = now; k; k /= 10)
{
int tmp = (now / k) % 10; //取出當前位數
//逆
if (tmp < 9) //1 -> 2, ...
now += k;
else
now -= 9 * k; //9 -> 0

if (!visited[now])
{
Q.push(now);
step[now] = step[cpy] + 1;
visited[now] = true;
}
if (now == t)
break;

now = cpy;

//順
if (tmp) //2 -> 1, ...
now -= k;
else
now += 9 * k; //0 -> 9

if (!visited[now])
{
Q.push(now);
step[now] = step[cpy] + 1;
visited[now] = true;
}
if (now == t)
break;

now = cpy;
}
}

printf("%d\n", step[t] ? step[t] : -1);
}

//init
memset(visited, false, sizeof visited);
memset(step, 0, sizeof step);
}

return 0;
}