SRM468 Div1 Medium(500) RoadOrFlightHard
動的計画法。何回離陸したかと直前が陸路か空路か、それぞれの最小所要時間を記憶しておく。
#include <vector> #include <algorithm> #include <limits> using namespace std; class RoadOrFlightHard { public: long long minTime( int N, int roadFirst, int roadProd, int roadAdd, int roadMod, int flightFirst, int flightProd, int flightAdd, int flightMod, int K ); }; long long RoadOrFlightHard::minTime( int N, int roadFirst, int roadProd, int roadAdd, int roadMod, int flightFirst, int flightProd, int flightAdd, int flightMod, int K ) { // T[k][0]:k回離陸して直前に陸路を選択した場合の最小所要時間 // T[k][1]:k回離陸して直前に空路を選択した場合の最小所要時間 vector<long long> T[2]; T[0] = T[1] = vector<long long>( K+1, LLONG_MAX/2 ); T[0][0] = 0; long long proad; // 直前の陸路の所要時間 long long pflight; // 直前の空路の所要時間 for ( int n=0; n<N; n++ ) { long long road, flight; if ( n == 0 ) road = roadFirst % roadMod, flight = flightFirst % flightMod; else road = ( proad * roadProd + roadAdd ) % roadMod, flight = ( pflight * flightProd + flightAdd ) % flightMod; vector<long long> t[2] = { T[0], T[1] }; // 陸路 for ( int k=0; k<=K; k++ ) T[0][k] = min( t[0][k], t[1][k] ) + road; // 空路 for ( int k=1; k<=K; k++ ) T[1][k] = min( t[0][k-1], t[1][k] ) + flight; proad = road; pflight = flight; } return min( *min_element( T[0].begin(), T[0].end() ), *min_element( T[1].begin(), T[1].end() ) ); }