某戀愛遊戲製作公司為了慶祝十周年,特別在網路上發布了一個遊戲,誰能通關拿到最佳結局,就能獲得新台幣一千萬的巨額獎金。遊戲的內容如下:
一個男孩遇見了心儀的對象,參賽者要幫助這個男孩在每個階段進行事件選擇,選擇後會進入下一個階段,然後再進行選擇 …… 直至結局階段。結局為何,取決於玩家所經歷的階段和事件。所有的結局中,只有一個路線能達成最佳結局。
礙於成本考量,公司決定對於每個報名的人收費。他們對收費的金額進行討論,最後討論出了一連串複雜的數學式子作為費用的計算公式,其中遊戲進行的總路線數是最關鍵的數值。你是公司的一名員工,你必須負責算出路線總數 R。
遊戲的設定如下:
- 遊戲共有 N 個階段,S0 為初始階段,SN-1 為結局階段。
- 對每個階段 Si,事件 Eij 會讓玩家進入到階段 Sj。
- 對於任意階段,玩家最多僅能經歷一次。即:不會有任何事件可以讓玩家回到曾經經歷過的階段。
- 不管中間的事件選擇是什麼,總是 S0 開始,SN-1 結束。
- 路線總數 R 不為 0。
- 不會有重複的重件(兩個階段至多只由一個事件連接)。
以上圖為例,這個遊戲共有 7 個不同路線可以到達 SN-1。
範例測資
範例輸入 | 範例輸出 |
---|---|
每組測資第一列有兩個正整數 N 及 E,N 表示階段的數量,階段分別編號 0 至 N-1,E(S-1 <= E <= 2×S)為事件的數量。接著有 E 列,每列有兩個整數 i、j,表示階段 Si 存在事件 Eij 能讓玩家進入階段 Sj。 | 每組測資輸出一個正整數 R,為路線總數。 |
9 12 0 1 0 2 0 3 0 5 0 7 3 4 1 4 4 6 7 6 6 8 2 8 5 8 | 5 |
10 14 0 1 0 2 1 3 1 4 1 5 1 6 2 6 3 9 4 9 5 9 6 7 6 8 7 9 8 9 | 7 |
解題思路
使用 BFS,並且使用 Map 來紀錄每一個點可以前往的點。宣告一個 ans 陣列預設為 0,並且將 ans[0] 設為 1。
在 BFS 中,將下一個點的 ans += 這個點的 ans。需要注意的是,要紀錄每一個點前面有幾個點需要先走過,每走到一個點的時候就將其前面的點的數量–,如果這個點前面的點都已經走完之後才將其作為下一次 BFS 的起點。
答案就是 ans[N-1]。
範例程式碼-ZeroJudge E999: 巨額獎金 (Bonus)
#include <iostream>
#include <vector>
#include <map>
using namespace std;
map<int, vector<int>>MAP;
map<int, int>ans, previous;
pair<int, int> p (const int a, const int b) {
pair<int, int>tmp;
tmp.first = a;
tmp.second = b;
return tmp;
}
void BFS(const vector<int>start) {
if (start.size() == 0) return;
vector<int>newStart;
for (int i = 0; i<start.size(); i++) {
const int current = start[i];
for (int j = 0 ; j<MAP[current].size(); j++) {
const int next = MAP[current][j];
previous[next]--;
ans[next] += ans[current];
if (previous[next] == 0) newStart.push_back(next);
}
}
BFS(newStart);
}
int main() {
cin.sync_with_stdio(0);
cin.tie(0);
int N, E;
cin >> N >> E;
for (int i = 0; i<E; i++) {
int a, b;
cin >> a >> b;
MAP[a].push_back(b);
previous[b]++;
}
ans[0] = 1;
vector<int>start;
start.push_back(0);
BFS(start);
cout << ans[N-1] << "\n";
}
//ZeroJudge E999
//Dr. SeanXD