CCF CSP 201604-4 游戲
問題描述
小明在玩一個電腦游戲,游戲在一個
n×
m的方格圖上進行,小明控制的角色開始的時候站在第一行第一列,目標是前往第
n行第
m列。
方格圖上有一些方格是始終安全的,有一些在一段時間是危險的,如果小明控制的角色到達一個方格的時候方格是危險的,則小明輸掉了游戲,如果小明的角色到達了第 n行第 m列,則小明過關。第一行第一列和第 n行第 m列永遠都是安全的。
每個單位時間,小明的角色必須向上下左右四個方向相鄰的方格中的一個移動一格。
經過很多次嘗試,小明掌握了方格圖的安全和危險的規律:每一個方格出現危險的時間一定是連續的。並且,小明還掌握了每個方格在哪段時間是危險的。
現在,小明想知道,自己最快經過幾個時間單位可以達到第 n行第 m列過關。
方格圖上有一些方格是始終安全的,有一些在一段時間是危險的,如果小明控制的角色到達一個方格的時候方格是危險的,則小明輸掉了游戲,如果小明的角色到達了第 n行第 m列,則小明過關。第一行第一列和第 n行第 m列永遠都是安全的。
每個單位時間,小明的角色必須向上下左右四個方向相鄰的方格中的一個移動一格。
經過很多次嘗試,小明掌握了方格圖的安全和危險的規律:每一個方格出現危險的時間一定是連續的。並且,小明還掌握了每個方格在哪段時間是危險的。
現在,小明想知道,自己最快經過幾個時間單位可以達到第 n行第 m列過關。
輸入格式
輸入的第一行包含三個整數
n,
m,
t,用一個空格分隔,表示方格圖的行數
n、列數
m,以及方格圖中有危險的方格數量。
接下來 t行,每行4個整數 r, c, a, b,表示第 r行第 c列的方格在第 a個時刻到第 b個時刻之間是危險的,包括 a和 b。游戲開始時的時刻為0。輸入數據保證 r和 c不同時為1,而且當 r為 n時 c不為 m。一個方格只有一段時間是危險的(或者說不會出現兩行擁有相同的 r和 c)。
接下來 t行,每行4個整數 r, c, a, b,表示第 r行第 c列的方格在第 a個時刻到第 b個時刻之間是危險的,包括 a和 b。游戲開始時的時刻為0。輸入數據保證 r和 c不同時為1,而且當 r為 n時 c不為 m。一個方格只有一段時間是危險的(或者說不會出現兩行擁有相同的 r和 c)。
輸出格式
輸出一個整數,表示小明最快經過幾個時間單位可以過關。輸入數據保證小明一定可以過關。
樣例輸入
3 3 3
2 1 1 1
1 3 2 10
2 2 2 10
2 1 1 1
1 3 2 10
2 2 2 10
樣例輸出
6
樣例說明
第2行第1列時刻1是危險的,因此第一步必須走到第1行第2列。
第二步可以走到第1行第1列,第三步走到第2行第1列,后面經過第3行第1列、第3行第2列到達第3行第3列。
第二步可以走到第1行第1列,第三步走到第2行第1列,后面經過第3行第1列、第3行第2列到達第3行第3列。
評測用例規模與約定
前30%的評測用例滿足:0 <
n,
m ≤ 10,0 ≤
t < 99。
所有評測用例滿足:0 < n, m ≤ 100,0 ≤ t < 9999,1 ≤ r ≤ n,1 ≤ c ≤ m,0 ≤ a ≤ b ≤ 100。
所有評測用例滿足:0 < n, m ≤ 100,0 ≤ t < 9999,1 ≤ r ≤ n,1 ≤ c ≤ m,0 ≤ a ≤ b ≤ 100。
解析
這是一個最短路的問題,但由於圖中邊的長度均為1,可以用廣度優先搜索解決。
題目中可以重復訪問節點,如果不加以限制就會陷入大量重復訪問。
雖然可以重復訪問一個位置,但是加上時間的維度,不能重復訪問了。因為在時間上重復訪問並不能得到更優的解或是本沒有解進而可以找到解。
代碼
C++
#include <cstdio> #include <queue> #define MAXN 101 using namespace std; int N, M, T; int dirs[4][2] = {{0,1},{0,-1},{1,0},{-1,0}}; bool visited[MAXN][MAXN][300]; int start[MAXN][MAXN]; int end[MAXN][MAXN]; struct Node { int x; int y; int g; Node(int x_, int y_, int g_) : x(x_), y(y_), g(g_) {} }; bool legal(int n, int m) { return n>=1 && n<=N && m>=1 && m<=M; } int main() { scanf("%d%d%d", &N, &M, &T); for(int t=0; t<T; t++) { int r, c, a, b; scanf("%d%d%d%d", &r, &c, &a, &b); start[r][c] = a; end[r][c] = b; } queue<Node> q; q.push(Node(1,1,0)); visited[1][1][0] = true; while(!q.empty()) { Node top = q.front(); q.pop(); if(top.x==N && top.y==M) { printf("%d", top.g); break; } for(int d=0; d<4; d++) { int nx = top.x + dirs[d][0]; int ny = top.y + dirs[d][1]; int ng = top.g + 1; if(legal(nx,ny) && (ng<start[nx][ny] || ng>end[nx][ny]) && !visited[nx][ny][ng]) { visited[nx][ny][ng] = true; q.push(Node(nx,ny,ng)); } } } }
