ZOJ-3103 Cliff Climbing
2014-09-09 09:32
405 查看
Cliff Climbing
Time Limit: 10 Seconds Memory Limit: 32768 KB
At 17:00, special agent Jack starts to escape from the enemy camp. There is a cliff in between the camp and the nearest safety zone. Jack has to climb the almost vertical cliff by stepping his feet on the blocks that cover the cliff. The cliff has slippery
blocks where Jack has to spend time to take each step. He also has to bypass some blocks that are too loose to support his weight. Your mission is to write a program that calculates the minimum time to complete climbing.
Figure D-1 shows an example of cliff data that you will receive. The cliff is covered with square blocks. Jack starts cliff climbing from the ground under the cliff, by stepping his left or right foot on one of the blocks marked with 'S' at the bottom row.
The numbers on the blocks are the "slippery levels". It takes t time units for him to safely put his foot on a block marked with t, where 1 <= t <= 9. He cannot put his feet on blocks marked with 'X'. He completes the climbing when
he puts either of his feet on one of the blocks marked with 'T' at the top row.
Figure D-1: Example of Cliff Data
Jack's movement must meet the following constraints. After putting his left (or right) foot on a block, he can only move his right (or left, respectively) foot. His left foot position (lx, ly) and his right foot position (rx, ry)
should satisfy lx < rx and | lx - rx | + | ly - ry | <= 3. This implies that, given a position of his left foot in Figure D-2 (a), he has to place his right foot on one of the nine blocks marked with blue
color. Similarly, given a position of his right foot in Figure D-2 (b), he has to place his left foot on one of the nine blocks marked with blue color.
Figure D-2: Possible Placements of Feet
Input
The input is a sequence of datasets. The end of the input is indicated by a line containing two zeros separated by a space. Each dataset is formatted as follows:
w h
s(1,1) ... s(1,w)
s(2,1) ... s(2,w)
...
s(h,1) ... s(h,w)
The integers w and h are the width and the height of the matrix data of the cliff. You may assume 2 <= w <= 30 and 5 <= h <= 60. Each of the following h lines consists of w characters delimited by a space.
The character s(y, x) represents the state of the block at position (x, y) as follows:
'S': Jack can start cliff climbing from this block.
'T': Jack finishes climbing when he reaches this block.
'X': Jack cannot put his feet on this block.
'1' - '9' (= t): Jack has to spend t time units to put either of his feet on this block.
You can assume that it takes no time to put a foot on a block marked with 'S' or 'T'.
Output
For each dataset, print a line only having a decimal integer indicating the minimum time required for the cliff climbing, when Jack can complete it. Otherwise, print a line only having "-1" for the dataset. Each line should not have any characters other
than these numbers.
Sample Input
Sample Output
————————————————————中秋后的分割线————————————————————
前言:这其实是中秋节之前做的一道题。想把中秋节当做分界线,今后要脱胎换骨!
思路:不必想太多,这就是一道SPFA的题目。在建图的时候,邻接矩阵存图,只要不是X,而且像是走迷宫一样,另一点可以直接到达,而且没有超过迷宫的边界的话,就存在一条边。但是因为左右脚是交替的,所以需要两张图,一张左脚图,另一张右脚图,松弛操作变成:
if(dis[左][v] > dis[右][u] + mat.val)
dis[左][v] = dis[右][u] + mat.val;
也就是说, 每次用一只脚松弛另一只脚,交替进行即可。
因为存在多个起点,所以所有起点全部入队。因为存在多个终点,所以取左右脚到达每个终点的最小值。
代码如下:
Time Limit: 10 Seconds Memory Limit: 32768 KB
At 17:00, special agent Jack starts to escape from the enemy camp. There is a cliff in between the camp and the nearest safety zone. Jack has to climb the almost vertical cliff by stepping his feet on the blocks that cover the cliff. The cliff has slippery
blocks where Jack has to spend time to take each step. He also has to bypass some blocks that are too loose to support his weight. Your mission is to write a program that calculates the minimum time to complete climbing.
Figure D-1 shows an example of cliff data that you will receive. The cliff is covered with square blocks. Jack starts cliff climbing from the ground under the cliff, by stepping his left or right foot on one of the blocks marked with 'S' at the bottom row.
The numbers on the blocks are the "slippery levels". It takes t time units for him to safely put his foot on a block marked with t, where 1 <= t <= 9. He cannot put his feet on blocks marked with 'X'. He completes the climbing when
he puts either of his feet on one of the blocks marked with 'T' at the top row.
Figure D-1: Example of Cliff Data
Jack's movement must meet the following constraints. After putting his left (or right) foot on a block, he can only move his right (or left, respectively) foot. His left foot position (lx, ly) and his right foot position (rx, ry)
should satisfy lx < rx and | lx - rx | + | ly - ry | <= 3. This implies that, given a position of his left foot in Figure D-2 (a), he has to place his right foot on one of the nine blocks marked with blue
color. Similarly, given a position of his right foot in Figure D-2 (b), he has to place his left foot on one of the nine blocks marked with blue color.
Figure D-2: Possible Placements of Feet
Input
The input is a sequence of datasets. The end of the input is indicated by a line containing two zeros separated by a space. Each dataset is formatted as follows:
w h
s(1,1) ... s(1,w)
s(2,1) ... s(2,w)
...
s(h,1) ... s(h,w)
The integers w and h are the width and the height of the matrix data of the cliff. You may assume 2 <= w <= 30 and 5 <= h <= 60. Each of the following h lines consists of w characters delimited by a space.
The character s(y, x) represents the state of the block at position (x, y) as follows:
'S': Jack can start cliff climbing from this block.
'T': Jack finishes climbing when he reaches this block.
'X': Jack cannot put his feet on this block.
'1' - '9' (= t): Jack has to spend t time units to put either of his feet on this block.
You can assume that it takes no time to put a foot on a block marked with 'S' or 'T'.
Output
For each dataset, print a line only having a decimal integer indicating the minimum time required for the cliff climbing, when Jack can complete it. Otherwise, print a line only having "-1" for the dataset. Each line should not have any characters other
than these numbers.
Sample Input
6 6 4 4 X X T T 4 7 8 2 X 7 3 X X X 1 8 1 2 X X X 6 1 1 2 4 4 7 S S 2 3 X X 2 10 T 1 1 X 1 X 1 X 1 1 1 X 1 X 1 1 1 X S S 2 10 T X 1 X 1 X 1 X 1 1 1 X 1 X 1 1 1 X S S 10 10 T T T T T T T T T T X 2 X X X X X 3 4 X 9 8 9 X X X 2 9 X 9 7 7 X 7 3 X X 8 9 X 8 9 9 9 6 3 X 5 X 5 8 9 9 9 6 X X 5 X 5 8 6 5 4 6 8 X 5 X 5 8 9 3 9 6 8 X 5 X 5 8 3 9 9 6 X X X 5 X S S S S S S S S S S 10 7 2 3 2 3 2 3 2 3 T T 1 2 3 2 3 2 3 2 3 2 3 2 3 2 3 2 3 2 3 4 3 2 3 2 3 2 3 2 3 5 3 2 3 1 3 2 3 2 3 5 2 2 3 2 4 2 3 2 3 5 S S 2 3 2 1 2 3 2 3 0 0
Sample Output
12 5 -1 22 12
————————————————————中秋后的分割线————————————————————
前言:这其实是中秋节之前做的一道题。想把中秋节当做分界线,今后要脱胎换骨!
思路:不必想太多,这就是一道SPFA的题目。在建图的时候,邻接矩阵存图,只要不是X,而且像是走迷宫一样,另一点可以直接到达,而且没有超过迷宫的边界的话,就存在一条边。但是因为左右脚是交替的,所以需要两张图,一张左脚图,另一张右脚图,松弛操作变成:
if(dis[左][v] > dis[右][u] + mat.val)
dis[左][v] = dis[右][u] + mat.val;
也就是说, 每次用一只脚松弛另一只脚,交替进行即可。
因为存在多个起点,所以所有起点全部入队。因为存在多个终点,所以取左右脚到达每个终点的最小值。
代码如下:
/* ID: j.sure.1 PROG: LANG: C++ */ /****************************************/ #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <cmath> #include <stack> #include <queue> #include <vector> #include <map> #include <string> #include <climits> #include <iostream> #define INF 0x3f3f3f3f using namespace std; /****************************************/ #define LIM nx >= 0 && nx < h && ny >= 0 && ny < w const int dir[2][9][2] = {{-2, -1, -1, -1, -1, -2, 0, -1, 0, -2, 0, -3, 1, -1, 1, -2, 2, -1}, {-2, 1, -1, 1, -1, 2, 0, 1, 0, 2, 0, 3, 1, 1, 1, 2, 2, 1}}; const int N = 65*35; int w, h, dis[2] , q , ans ; bool inq[2] ; char mat[65][35]; void spfa(int rear) { int fron = 0; while(fron < rear) { int u = q[fron%N]; fron++; int x = u / w, y = u % w; for(int f = 0; f < 2; f++) { if(inq[1-f][u]) {//右脚在队列当中 inq[1-f][u] = false; for(int d = 0; d < 9; d++) { int nx = x + dir[f][d][0], ny = y + dir[f][d][1];//踏出左脚 if(LIM && mat[nx][ny] != 'X') { int v = nx*w + ny, val; if(mat[nx][ny] == 'S' || mat[nx][ny] == 'T') val = 0; else val = mat[nx][ny] - '0'; if(dis[f][v] > dis[1-f][u] + val) { dis[f][v] = dis[1-f][u] + val; if(!inq[f][v]) {//新的左脚 inq[f][v] = true; q[rear%N] = v; rear++; } } } } } } } } int main() { #ifdef J_Sure // freopen("000.in", "r", stdin); // freopen(".out", "w", stdout); #endif while(scanf("%d%d", &w, &h), w||h) { int rear = 0; for(int i = 0; i <= h*w; i++) { dis[0][i] = dis[1][i] = INF; inq[0][i] = inq[1][i] = 0; } int cnt = 0; for(int i = 0 ; i < h; i++) { for(int j = 0; j < w; j++) { scanf(" %c", &mat[i][j]); int u = i*w + j; if(mat[i][j] == 'S') { q[rear%N] = u; rear++; dis[0][u] = dis[1][u] = 0; inq[0][u] = inq[1][u] = true; }//起点全部入队 if(mat[i][j] == 'T') { ans[cnt++] = i*w + j; } } } spfa(rear); int ret = INF; for(int i = 0; i < cnt; i++) { ret = min(ret, min(dis[0][ans[i]], dis[1][ans[i]])); }//取所有终点的左脚、右脚到达的最小值 if(ret == INF) puts("-1"); else printf("%d\n", ret); } return 0; }
相关文章推荐
- zoj 3103 Cliff Climbing (SPFA)
- ZOJ-3103 Cliff Climbing 最短路
- zoj 3103 Cliff Climbing(spfa )
- zoj 3103 Cliff Climbing 优先队列+BFS
- ZOJ Problem Set - 1088 System Overload
- ZOJ 3232 It's not Floyd Algorithm --强连通分量+Floyd
- ZOJ 3684 Destroy
- Seven Segment Display ZOJ - 3962
- ZOJ 2679 Old Bill(STL应用)
- ZOJ - 1586 QS Network (最小生成树 Kruskal)
- ZOJ 3209 Treasure Map (DLX精确覆盖问题)
- ZOJ 3929 Deque and Balls
- ZOJ-1004-Anagrams by Stack
- ZOJ 1015 弦图的判断
- ZOJ - 2750 Idiomatic Phrases Game (最短路径)
- ZOJ 3760 Treasure Hunting(最大流)
- zoj1026 Modular multiplication of polynomials
- zoj 1001 A+B Python版本
- Lucas定理简单运用的五题之hdu3037 hdu 3944 fzu 2020 zoj 3557 hdu4349
- zoj 3228(ac自动机)