SRM492 Div1 Medium(550) TimeTravellingTour
A→B→C→D―(タイムマシン)→B→E という移動はBの時点でCとEに分岐して調査すると考える。都市iから開始してcities[j..k]を調査するコストをc[i][j][k]とすると
c[i][j][k] = min( {c[l][i][k]+road[i][j][k]}∪{c[i][j][m]+c[i][m+1][k]} )。
ただし、lはiと繋がっている都市、j≦m<k。
#include <string> #include <vector> #include <numeric> #include <sstream> using namespace std; class TimeTravellingTour{public: long long determineCost( int N, vector <int> cities, vector <string> roads ) { long long INF = 0x100000000000000ll; // [i][j] 都市iと都市jの間のコスト static long long road[64][64]; for ( int i=0; i<64*64; i++ ) road[0][i] = INF; string s = accumulate( roads.begin(), roads.end(), string() ); stringstream ss(s); int a, b, c; char t; while ( ss>>a>>t>>b>>t>>c ) road[a][b] = road[b][a] = c; // [i][j][k] 都市iから開始して、cities[j..k]の都市を調査する最小コスト static long long cost[64][64][64]; for ( int i=0; i<64*64*64; i++ ) cost[0][0][i] = INF; int M = (int)cities.size(); for ( int w=0; w<M; w++ ) for ( int c1=0; c1+w<M; c1++ ) { int c2 = c1 + w; // 都市にいれば調査可能 if ( w == 0 ) cost[cities[c1]][c1][c2] = 0; // タイムマシン for ( int i=0; i<N; i++ ) for ( int j=c1; j<c2; j++ ) cost[i][c1][c2] = min( cost[i][c1][c2], cost[i][c1][j]+cost[i][j+1][c2] ); // 道路 bool up; do { up = false; for ( int i=0; i<N; i++ ) for ( int j=0; j<N; j++ ) if ( cost[i][c1][c2] > cost[j][c1][c2]+road[i][j] ) cost[i][c1][c2] = cost[j][c1][c2]+road[i][j], up = true; } while ( up ); } return cost[0][0][M-1]<INF ? cost[0][0][M-1] : -1; }};