Div2 1000 Thirteen
駅駅間の所要時間が2次元配列で与えられる.(A-Zは1〜26,a-zは27〜52,#は通行不可)
目的地に達するまでに経由する駅においてスタートからの時間が13の倍数になってはいけない.(※)
0番の駅からN-1番の駅まで達するのに要する最短時間を求めよ.
(※)4駅で移動した時,各駅間の所要時間が順に T0, T1, T2 だとするとき,T0, T0+T1, T0+T1+T2 のいずれも 13 の倍数になってはいけない.
考え方
ダイクストラを[N][13]で行えばOK.というのも[13]の方は達成時間の(mod 13)で分類すればいいだけなので.[N-1][*]の更新がされた時点でreturnすれば大丈夫.
コード
#include <set> #include <string> #include <vector> using namespace std; struct Lap { int time, city; Lap(int a, int b) : time(a), city(b) {} }; bool operator<(const Lap& a, const Lap& b) { if( a.time == b.time ) { return a.city < b.city; } return a.time < b.time; } class Thirteen { int distance(char c) { if( 'A' <= c && c <= 'Z' ) return c - 'A' + 1; return c - 'a' + 27; } public: int calcTime(vector <string> city) { const int N = city.size(); vector< vector<int> > shortest(N, vector<int>(13, 99999)); set<Lap> q; shortest[0][0] = 0; q.insert(Lap(0, 0)); while( !q.empty() ) { Lap l = *q.begin(); q.erase(q.begin()); if( l.city == city.size() - 1 ) return l.time; string& dist = city[l.city]; for( int i = 0 ; i < city.size() ; ++i ) { if( dist[i] == '#' ) continue; int tt = l.time + distance(dist[i]); int ff = tt % 13; if( ff == 0 ) continue; if( shortest[i][ff] > tt ) { shortest[i][ff] = tt; q.insert(Lap(tt, i)); } } } return -1; } };