問題 - Railway tickets • 数直線上のN個の駅(2以上10000以下) • 距離に応じたチケット料金 – 距離L1 までは値段 C1 – 距離L2 までは値段 C2 – 距離L3 までは値段 C3 • 2駅間の最安チケット料金を求める 細かい条件 • L や C は int に収まる – 1<=L1<L2<L3<=10^9, 1<=C1<C2<C3<=10^9 – int の最大値は 2G~2*10^9+α • 全ての駅は連結している – 駅間はL3を超えないので道はある • 最初の駅は座標 0 • 残りの駅は絶対座標が与えられる 方針 • 力ずくの探索→10000駅あるので無理 • 主なやり方は2通り – グラフと見立ててダイクストラ – DP(動的計画法) • ここでは最も簡便と思われるDPを説明 – 実際にスタッフが作成したソースを元に説明 入力データ構造 • 問題文通りに素直に入力 int L[3], C[3]; int numStation; int indexStartStation; int indexEndStation; vector<int> positionOfStations; 入力データのパーズ • 駅の番号は内部0-origin,外部1-origin とする { } // load data cin >> L[0] >> L[1] >> L[2]; cin >> C[0] >> C[1] >> C[2]; cin >> numStation; positionOfStations.resize(numStation); cin >> indexStartStation; indexStartStation--; cin >> indexEndStation; indexEndStation--; positionOfStations[0] = 0; for(int i = 1; i < positionOfStations.size(); i++) { cin >> positionOfStations[i]; } // fori 左右の入れ替え • 始駅の駅番号sと終駅の駅番号dがs<dとな るように変換 if(indexStartStation > indexEndStation) swap(indexEndStation, indexStartStation); Dynamic Programming 始駅 終駅 駅番号 2 3 4 5 6 位置 コスト 20 0 34 15 48 38 89 122 距離L1まで 38+C1 距離L2まで 15+C2 距離L3まで 0+C3 最も安い コストを 選択する DPの初期化 • 最小コストは10^9を超えないので10^9+1で 初期化 vector<int> minimalCost(numStation, 1000000001); minimalCost[indexStartStation] = 0; DPループ • ある駅を固定し、前の駅を距離L3まで考慮 for(int idx = indexStartStation + 1; idx <= indexEndStation; idx++) { int lengthType = 0; int indexOfPrevStation = idx - 1; while(indexOfPrevStation >= 0 && lengthType < 3) { while(lengthType < 3 && abs(positionOfStations[idx] – positionOfStations[indexOfPrevStation]) > L[lengthType]) { lengthType++; } if(lengthType < 3) { minimalCost[idx] = min<int>(minimalCost[idx], minimalCost[indexOfPrevStation] + C[lengthType]); } indexOfPrevStation--; } } 結果の表示 cout << minimalCost[indexEndStation] << endl ;
© Copyright 2024 ExpyDoc