MemberSRM468 Div1 500 RoadOrFlightHard

本番で解けなかった問題.
DP中で,飛行機を使う最適な区間は…とか考えてて意味不明な事になってたものの,

  • 飛行機でK回目のフライト中
  • K回のフライトを終えて陸地を移動中


という状態だけ保存してDPすれば良かった.

この手の問題はまだまだ訓練が必要そう….

#include <iostream>
#include <vector>

using namespace std;

class RoadOrFlightHard{
private:
    void generate(int N, vector<long long> &res, int first, int prod, int add, int mod){
        res.resize(N);
        res[0] = first%mod;
        for(int i=1;i<N;i++)
            res[i] = (res[i-1]*prod+add)%mod;
    }
public:
    long long minTime(int N, int roadFirst, int roadProd, int roadAdd, int roadMod, int flightFirst, int flightProd, int flightAdd, int flightMod, int K){
        vector<long long> road, flight;
        generate(N, road, roadFirst, roadProd, roadAdd, roadMod);
        generate(N, flight, flightFirst, flightProd, flightAdd, flightMod);
        long long curR[41], curF[41], nextR[41], nextF[41];
        memset(curR, 0, sizeof(curR));
        memset(curF, 0, sizeof(curF));
        for(int i=0;i<N;i++){
            nextR[0] = curR[0]+road[i];
            nextF[0] = (long long)1e15;
            for(int j=1;j<=K;j++){
                nextR[j] = min(curR[j], curF[j])+road[i];
                nextF[j] = min(curR[j-1], curF[j])+flight[i];
            }
            memcpy(curR, nextR, sizeof(curR));
            memcpy(curF, nextF, sizeof(curF));
        }
        return min(curR[K], curF[K]);
    }
};