5793. 【NOIP2008模拟】小S练跑步
(File IO): input:run.in output:run.out
Time Limits:
2000 ms Memory Limits: 524288 KB Detailed Limits
Goto ProblemSet
Description
小S是一个爱锻炼的孩子,他在放假期间坚持在A公园练习跑步。
但不久后,他就开始为在重复的地点练习感到厌烦了,他就打算去B公园跑步。
但是小S由于没有去过B公园,他不知道B公园是否适合练习跑步,又不知道在B公园怎样跑是最优的。所以小S就去B公园进行了一番勘测。
小S在进行了一番勘测后,画出了一张地图,地图每一个位置上都辨识了小S到达该位置后不能往哪一个方位移动。其中有5种表示的符号:“U”代表不能向上移动,“D”代表不能向下移动,“L”代表不能向左移动,“R”代表不能向右移动,如果该位置有障碍物,小S到达那里后无法继续训练,就用“S”来代表。整个公园共有n行m列,小S会从第1行第1列出发,到第n行第m列结束他的练习。
现在小S想要知道,从起点(即第1行第1列)到终点(第n行第m列),途中最少要改变几次方向(即上一次移动的方向和这一次移动的方向不一样)?
注意:小S如在训练途中离开公园(即地图范围),则算是结束训练。
但不久后,他就开始为在重复的地点练习感到厌烦了,他就打算去B公园跑步。
但是小S由于没有去过B公园,他不知道B公园是否适合练习跑步,又不知道在B公园怎样跑是最优的。所以小S就去B公园进行了一番勘测。
小S在进行了一番勘测后,画出了一张地图,地图每一个位置上都辨识了小S到达该位置后不能往哪一个方位移动。其中有5种表示的符号:“U”代表不能向上移动,“D”代表不能向下移动,“L”代表不能向左移动,“R”代表不能向右移动,如果该位置有障碍物,小S到达那里后无法继续训练,就用“S”来代表。整个公园共有n行m列,小S会从第1行第1列出发,到第n行第m列结束他的练习。
现在小S想要知道,从起点(即第1行第1列)到终点(第n行第m列),途中最少要改变几次方向(即上一次移动的方向和这一次移动的方向不一样)?
注意:小S如在训练途中离开公园(即地图范围),则算是结束训练。
Input
第1行两个整数n和m,它们的定义请看【题目描述】。
第2~n+1行,每行有m个字符,表示小S的移动方向。
第2~n+1行,每行有m个字符,表示小S的移动方向。
Output
如果小S从第1行第1列出发无论如何都到达不了第n行第m列,输出“No Solution”,否则输出小S途中最少要改变方向的次数。
Sample Input
3 3 ULL LDU SUD
Sample Output
1 【样例解释】 小S先向右移动移动了2格,再向下移动2格,就到达了终点,这样只用改变一次方向。
Data Constraint
【数据范围限制】
10%的数据是题目的馈赠。
30%的数据,1≤n,m≤10。
50%的数据,1≤n,m≤50。
70%的数据,1≤n,m≤250。
100%的数据,1≤n,m≤500.
其中50%的数据是先构造出路径,再构造地图的。
100%数据是随机构造的。
10%的数据是题目的馈赠。
30%的数据,1≤n,m≤10。
50%的数据,1≤n,m≤50。
70%的数据,1≤n,m≤250。
100%的数据,1≤n,m≤500.
其中50%的数据是先构造出路径,再构造地图的。
100%数据是随机构造的。
做法:纯粹的暴力╮(╯_╰)╭,考验代码能力。。。
这里给出一个比较丑的打法,跑了1500ms,看到有人跑了50ms。。
代码如下:


1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <string> 5 #define M 507 6 using namespace std; 7 int n, m, map[M][M], dis[M][M][5], list[30000000][4]; 8 string s; 9 int dy[5] = {0, 0, 0, -1, 1}; 10 int dx[5] = {0, -1, 1, 0, 0}; 11 12 void init() 13 { 14 scanf("%d%d", &n, &m); 15 for (int i = 1; i <= n; i++) 16 { 17 cin >> s; 18 for (int j = 0; j < m; j++) 19 { 20 if (s[j] == 'U') map[i][j + 1] = 1; 21 if (s[j] == 'D') map[i][j + 1] = 2; 22 if (s[j] == 'L') map[i][j + 1] = 3; 23 if (s[j] == 'R') map[i][j + 1] = 4; 24 if (s[j] == 'S') map[i][j + 1] = 5; 25 } 26 } 27 } 28 29 bool check(int x, int y, int w, int to) 30 { 31 if (map[x][y] == 5 &&(x != n || y != m)) return 0; 32 if (x > n || x < 1) return 0; 33 if (y > m || y < 1) return 0; 34 if (to >= dis[x][y][w]) return 0; 35 if (to >= dis[x][y][0] + 1) return 0; 36 dis[x][y][0] = min(dis[x][y][0], to); 37 dis[x][y][w] = to; 38 return 1; 39 } 40 41 void Bfs() 42 { 43 int head = 0, tail = 0; 44 memset(dis, 0x7f7f7f7f, sizeof(dis)); 45 dis[1][1][1] = 0; 46 dis[1][1][2] = 0; 47 dis[1][1][3] = 0; 48 dis[1][1][4] = 0; 49 for (int i = 1; i <= 4; i++) 50 if (map[1][1] != i) 51 { 52 list[++tail][1] = 1; 53 list[tail][0] = 1; 54 list[tail][2] = i; 55 } 56 while (head < tail) 57 { 58 int u = list[++head][0], v = list[head][1], now = list[head][2], val = list[head][3]; 59 for (int i = 1; i <= 4; i++) 60 if (map[u][v] != i) 61 { 62 int ain_u = u + dx[i], ain_v = v + dy[i]; 63 int W = val; 64 if (now != i) W++; 65 if (!check(ain_u, ain_v, i, W)) continue; 66 list[++tail][0] = ain_u; 67 list[tail][1] = ain_v; 68 list[tail][2] = i; 69 list[tail][3] = W; 70 } 71 } 72 int ans = 0x7f7f7f7f; 73 for (int i = 1; i <= 4; i++) 74 ans = min(ans, dis[n][m][i]); 75 if (ans == 0x7f7f7f7f) printf("No Solution"); 76 else printf("%d", ans); 77 } 78 79 int main() 80 { 81 freopen("run.in", "r", stdin); 82 freopen("run.out", "w", stdout); 83 init(); 84 Bfs(); 85 }