CCF201604-4 遊戲(100分)
試題編號: | 201604-4 |
試題名稱: | 遊戲 |
時間限制: | 1.0s |
記憶體限制: | 256.0MB |
問題描述: |
問題描述 小明在玩一個電腦遊戲,遊戲在一個n×m的方格圖上進行,小明控制的角色開始的時候站在第一行第一列,目標是前往第n行第m列。 輸入格式 輸入的第一行包含三個整數n, m, t,用一個空格分隔,表示方格圖的行數n、列數m,以及方格圖中有危險的方格數量。 輸出格式 輸出一個整數,表示小明最快經過幾個時間單位可以過關。輸入資料保證小明一定可以過關。 樣例輸入 3 3 3 樣例輸出 6 樣例說明 第2行第1列時刻1是危險的,因此第一步必須走到第1行第2列。 評測用例規模與約定 前30%的評測用例滿足:0 < n, m ≤ 10,0 ≤ t < 99。 |
問題描述:(參見上文)。
問題分析:
這是一個求最短路徑的問題,即求最優問題,通常用BFS(廣度優先搜尋)來實現。本題也用BFS來實現,比較難以考慮到的是,需要一個三維的標誌來避免重複搜尋。除了行列座標外,還需要考慮時間因素,所以是三維的。因為一些格在某個時間範圍是危險的,不可進入,但是這個時間範圍之外,是可以隨意進入的。所以有時候需要在一些地方踱步,等過了這段時間再前行,就不能簡單地限制為進入過的格不能再進入。
程式說明:
把格的危險時間範圍儲存在陣列visited[][][]中,使得程式邏輯變得更加簡潔,同時也節省了儲存。其他都是套路。
陣列visited[][][]的第3維座標之所以為300+1,是計算出來的。從左上角到右下角最多走200步,時間範圍a,b<=100,那麼安全走到右下角使用的最多時間<=300,下標0不使用,所以是300+1。
提交後得100分的C++語言程式如下:
/* CCF201604-4 遊戲 */
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
const int N = 100;
const int DIRECTSIZE = 4;
struct direct {
int drow, dcol;
} direct[DIRECTSIZE] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
int visited[N+1][N+1][300+1];
struct node {
int row, col, level;
};
int bfs(int n, int m)
{
node start, front, v;
start.row = 1;
start.col = 1;
start.level = 0;
queue<node> q;
q.push(start);
while(!q.empty()) {
front = q.front();
q.pop();
// 到達終點則結束
if(front.row == n && front.col == m)
return front.level;
for(int i=0; i<DIRECTSIZE; i++) {
// 移動一格
v.row = front.row + direct[i].drow;
v.col = front.col + direct[i].dcol;
v.level = front.level + 1;
// 行列越界則跳過
if(v.row < 1 || v.row > n || v.col < 1 || v.col > m)
continue;
// 已經訪問過的點不再訪問
if(visited[v.row][v.col][v.level])
continue;
// 向前搜尋:標記v點為已經訪問過,v點加入佇列中
visited[v.row][v.col][v.level] = 1;
q.push(v);
}
}
return 0;
}
int main()
{
int n, m, t, r, c, a, b;
// 變數初始化
memset(visited, 0, sizeof(visited));
// 輸入資料
cin >> n >> m >> t;
for(int i=1; i<=t; i++) {
cin >> r >> c >> a >> b;
// 設定方格危險時間,使之那些時間不可進入
for(int j=a; j<=b; j++)
visited[r][c][j] = 1;
}
// BFS搜尋
int ans = bfs(n, m);
// 輸出結果
cout << ans << endl;
return 0;
}