Problem p00743 (C++) — buggy submission, verdict: Time Limit Exceeded

#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
using namespace std;

#define REP(i, a, n) for (i = (a); i < (int)(n); i++)
#define rep(i, n) REP(i, 0, n)

int speed[33][33], dist[33][33];
bool used[33][33][33];
double dp[33][33][33]; // [ツ個サツ催敖づ個都ツ市][ツ前ツづ個都ツ市][ツ堕ャツ度]
const double inf = 999999999.0;

struct state {
  int no, pr, sp;
  double t;

  state(int n, int p, int s, double _t) : no(n), pr(p), sp(s), t(_t) {}
  bool operator<(const state &a) const { return t > a.t; }
};

int main() {
  int i, j, k, n, u, m, s, g;
  while (cin >> n >> m, n | m) {

    // init
    rep(i, 33) rep(j, 33) rep(k, 33) dp[i][j][k] = inf;
    memset(speed, -1, sizeof(speed));
    memset(dist, -1, sizeof(dist));
    memset(used, false, sizeof(used));

    // input
    cin >> s >> g;
    rep(i, m) {
      int x, y, d, c;
      cin >> x >> y >> d >> c;
      dist[x][y] = dist[y][x] = d;
      speed[x][y] = speed[y][x] = c;
    }

    priority_queue<state> q;
    // start

    REP(i, 1, n + 1) if (dist[s][i] != -1) {
      dp[i][s][1] = (double)dist[s][i];
      q.push(state(i, s, 1, (double)dist[s][i]));
    }

    while (!q.empty()) {
      int now = q.top().no;
      int prev = q.top().pr;
      int sp = q.top().sp;
      double t = dp[now][prev][sp];

      // printf("dp[%d][%d][%d] = %lf\\n",now,prev,sp,t);
      q.pop();

      if (now == g && sp == 1)
        break;
      if (used[now][prev][sp])
        continue;
      used[now][prev][sp] = true;

      REP(i, 1, n + 1)
      if (dist[now][i] != -1 &&
          prev != i) { // ツ篠淞づ可行ツつォツつスツつ「ツ都ツ市
        for (int v = sp - 1; v <= sp + 1; v++) {
          if (v <= 0 || v > speed[now][i])
            continue;

          if (dp[i][now][v] > t + (double)dist[now][i] / (double)v) {
            double cost = t + (double)dist[now][i] / (double)v;
            dp[i][now][v] = cost;
            q.push(state(i, now, v, cost));
          }
        }
      }
    }

    double res = inf;
    REP(i, 1, n + 1) if (dp[g][i][1] != inf) res = min(res, dp[g][i][1]);
    if (res == inf) {
      puts("unreachable");
    } else {
      printf("%lf\\n", res);
    }
  }

  return 0;
}

Error: TLE

Fixed submission:

#include <climits>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <string>
using namespace std;

#define REP(i, a, n) for (int i = (a); i < (int)(n); ++i)
#define rep(i, n) REP(i, 0, n)
#define DEB 0

class state {
public:
  int now, prev, speed;
  double cost;
  state(int n, int p, int s, double c) {
    now = n;
    prev = p;
    speed = s;
    cost = c;
  }
  bool operator<(const state &a) const { return cost > a.cost; }
};

int n, m;
int s, g;
int edge[32][32];
int speed[32][32];
double dp[32][32][32]; //[now][prev][speed]
const double inf = 9999999999.0;

int main() {

  while (cin >> n >> m, n | m) {
    memset(edge, -1, sizeof(edge));
    rep(i, 32) rep(j, 32) rep(k, 32) dp[i][j][k] = inf;
    cin >> s >> g;
    rep(i, m) {
      int a, b, c, d;
      cin >> a >> b >> c >> d;
      edge[a - 1][b - 1] = edge[b - 1][a - 1] = c;
      speed[a - 1][b - 1] = speed[b - 1][a - 1] = d;
    }

    double ans = inf;
    priority_queue<state> q;
    q.push(state(s - 1, s - 1, 0, 0.0));
    dp[s - 1][s - 1][0] = 0.0;

    while (!q.empty()) {
      int now = q.top().now;
      int prev = q.top().prev;
      int sp = q.top().speed;
      double c = q.top().cost;
      double tmp;
      q.pop();

#if DEB
      printf("now:%d  prev:%d  sp:%d  cost:%lf\\n", now, prev, sp, c);
#endif

      if (now == g - 1 & sp == 1) {
        ans = c;
        break;
      }

      rep(i, n) if (edge[now][i] != -1 && prev != i) {
        if (sp > 0 && sp <= speed[now][i]) {
          tmp = c + (double)edge[now][i] / (double)sp;
          if (dp[i][now][sp] > tmp) {
            dp[i][now][sp] = tmp;
            q.push(state(i, now, sp, tmp));
          }
        }
        if (sp + 1 <= speed[now][i]) {
          tmp = c + (double)edge[now][i] / (double)(sp + 1);
          if (dp[i][now][sp + 1] > tmp) {
            dp[i][now][sp + 1] = tmp;
            q.push(state(i, now, sp + 1, tmp));
          }
        }
        if (sp - 1 > 0 && sp - 1 <= speed[now][i]) {
          tmp = c + (double)edge[now][i] / (double)(sp - 1);
          if (dp[i][now][sp - 1] > tmp) {
            dp[i][now][sp - 1] = tmp;
            q.push(state(i, now, sp - 1, tmp));
          }
        }
      }
    }
    if (ans == inf) {
      puts("unreachable");
    } else {
      printf("%.6lf\\n", ans);
    }
  }
  return 0;
}