Mr. リトー郵便局

http://rose.u-aizu.ac.jp/onlinejudge/ProblemSet/description.jsp?id=2200&lang=jp
Warshall-Floyd で陸路のみ・海路のみを用いた場合のそれぞれの最短経路を求めた後に DP.
街 j に船がある場合の i 番目の集配地への最小コストを dp[i][j] は,i 番目の集配地を route[i] とすると

dp[i][j] = min {
            i-1 番目の集配地から陸路のみで移動したときのコスト,
            i-1 番目の集配地からある街 k に陸路で移動し,街 k から街 j まで海路で移動し,街 j から陸路で移動したときのコスト
           }
         = min {
            dp[i-1][j] + distL[route[i-1]][route[i]],
            dp[i-1][k] + distL[route[i-1]][k] + distS[k][j] + distL[j][route[i]] for each k
           }

となる.O(R*N^2)

#include <iostream>
using namespace std;

static const int INF = 1000000;
int distS[200][200], distL[200][200];
int route[10000];
int dp[10000][200];

int main()
{
  int N, M;
  while (cin >> N >> M && !(N == 0 && M == 0)) {
    for (int i = 0; i < N; i++) {
      for (int j = 0; j < N; j++) {
        distS[i][j] = distL[i][j] = INF;
      }
      distS[i][i] = distL[i][i] = 0;
    }

    for (int i = 0; i < M; i++) {
      int x, y, t;
      char sl;
      cin >> x >> y >> t >> sl;
      x--;  y--;
      if (sl == 'S') {
        distS[x][y] = distS[y][x] = t;
      } else {
        distL[x][y] = distL[y][x] = t;
      }
    }

    int R;
    cin >> R;
    for (int i = 0; i < R; i++) {
      cin >> route[i];
      route[i]--;
    }

    for (int k = 0; k < N; k++) {
      for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
          distS[i][j] = min(distS[i][j], distS[i][k] + distS[k][j]);
          distL[i][j] = min(distL[i][j], distL[i][k] + distL[k][j]);
        }
      }
    }

    for (int j = 0; j < N; j++) {
      dp[0][j] = distS[route[0]][j];
    }
    for (int i = 1; i < R; i++) {
      for (int j = 0; j < N; j++) {
        dp[i][j] = dp[i-1][j] + distL[route[i-1]][route[i]];
        for (int k = 0; k < N; k++) {
          dp[i][j] = min(dp[i][j], dp[i-1][k] + distL[route[i-1]][k] + distS[k][j] + distL[j][route[i]]);
        }
      }
    }

    int ans = INF;
    for (int i = 0; i < N; i++) {
      ans = min(ans, dp[R-1][i]);
    }
    cout << ans << endl;
  }
  return 0;
}