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

#include <bits/stdc++.h>
using namespace std;

const long double EPS = 1e-10;
const int H = 500;
const int W = 500;
const int dy[4] = {-1, 0, 1, 0};
const int dx[4] = {0, -1, 0, 1};

struct P {
  int x, y;
  P(int x = 0, int y = 0) : x(x), y(y) {}
};

struct state {
  int x, y, cnt;
  state(int x = 0, int y = 0, int cnt = 0) : x(x), y(y), cnt(cnt) {}
  bool operator<(const state &s) const { return cnt < s.cnt; }
};

int w, h, dis_go[H][W], dis_sp[H][W];
long double cnt_nowall;
P st, go;
vector<P> v;
bool wall[H][W];

void init_dis() {
  queue<state> q;
  state u, u2;

  cnt_nowall = 0;
  for (int i = 1; i < h - 1; i++) {
    for (int j = 1; j < w - 1; j++) {
      dis_go[i][j] = dis_sp[i][j] = -1;
      cnt_nowall += !wall[i][j];
    }
  }

  for (q.push(state(go.x, go.y, 0)); !q.empty();) {
    u = q.front();
    q.pop();
    for (int i = 0; i < 4; i++) {
      u2 = state(u.x + dx[i], u.y + dy[i], u.cnt + 1);
      if (!wall[u2.y][u2.x] &&
          (dis_go[u2.y][u2.x] == -1 || dis_go[u2.y][u2.x] > u2.cnt)) {
        dis_go[u2.y][u2.x] = u2.cnt;
        q.push(u2);
      }
    }
  }

  for (int i = 0; i < v.size(); i++) {
    for (q.push(state(v[i].x, v[i].y, 0)); !q.empty();) {
      u = q.front();
      q.pop();
      for (int j = 0; j < 4; j++) {
        u2 = state(u.x + dx[j], u.y + dy[j], u.cnt + 1);
        if (!wall[u2.y][u2.x] &&
            (dis_sp[u2.y][u2.x] == -1 || dis_sp[u2.y][u2.x] > u2.cnt)) {
          dis_sp[u2.y][u2.x] = u2.cnt;
          q.push(u2);
        }
      }
    }
  }
}

long double a_ruiseki[H * W], b_ruiseki[H * W], g_ruiseki[H * W];

void calc_exp_init() {
  vector<state> pv;

  for (int i = 1; i < h - 1; i++) {
    for (int j = 1; j < w - 1; j++) {
      if (!wall[i][j]) {
        pv.push_back(state(j, i, dis_go[i][j] - dis_sp[i][j]));
        if (dis_sp[i][j] == -1)
          pv[pv.size() - 1].cnt = -2;
        else if (dis_go[i][j] == -1)
          pv[pv.size() - 1].cnt = -1;
        else if (dis_go[i][j] < dis_sp[i][j])
          pv[pv.size() - 1].cnt = 0;
      }
    }
  }
  fill(a_ruiseki, a_ruiseki + H * W, 0);
  fill(b_ruiseki, b_ruiseki + H * W, 0);
  fill(g_ruiseki, g_ruiseki + H * W, 0);

  sort(pv.begin(), pv.end());

  a_ruiseki[h * w - 1] = 1.0;
  for (int i = 0; i < pv.size(); i++) {
    if (pv[i].cnt == -2) { // dis_sp[i][j] == -1
      g_ruiseki[0] += (long double)dis_go[pv[i].y][pv[i].x] / cnt_nowall;

    } else if (pv[i].cnt == -1) { // dis_go[i][j] == -1
      b_ruiseki[h * w - 1] +=
          (long double)dis_sp[pv[i].y][pv[i].x] / cnt_nowall;
      a_ruiseki[h * w - 1] -= (long double)1.0 / cnt_nowall;

    } else if (pv[i].cnt == 0) {
      // b_ruiseki[h*w-1] += (long double)dis_sp[pv[i].y][pv[i].x] / cnt_nowall;
      g_ruiseki[1] += (long double)dis_go[pv[i].y][pv[i].x] / cnt_nowall;

    } else {
      b_ruiseki[pv[i].cnt] +=
          (long double)dis_sp[pv[i].y][pv[i].x] / cnt_nowall;
      g_ruiseki[pv[i].cnt + 1] +=
          (long double)dis_go[pv[i].y][pv[i].x] / cnt_nowall;
      a_ruiseki[pv[i].cnt] -= (long double)1.0 / cnt_nowall;
    }
  }

  for (int i = 0; i < h * w - 1; i++) {
    g_ruiseki[i + 1] += g_ruiseki[i];
  }
  for (int i = h * w - 1; i > 0; i--) {
    b_ruiseki[i - 1] += b_ruiseki[i];
    a_ruiseki[i - 1] += a_ruiseki[i];
  }
}

long double calc_exp(int base) {
  long double a = 1.0, b = 0.0, exp_go = 0.0;

  /*
  for(int i=1;i<h-1;i++){
    for(int j=1;j<w-1;j++){
      if(!wall[i][j]){
        if(dis_go[i][j] == -1 || dis_sp[i][j] != -1 && dis_go[i][j] >=
  dis_sp[i][j] + base){ a -= 1.0 / cnt_nowall; b += (long double)dis_sp[i][j] /
  cnt_nowall; } else { exp_go += (long double)dis_go[i][j] / cnt_nowall;
        }
      }
    }
  }
  */

  // printf("g %d: %.10Lf %.10Lf\\n", base, g_ruiseki[base], exp_go);
  // printf("b %d: %.10Lf %.10Lf\\n", base, b_ruiseki[base], b);
  // printf("a %d: %.10Lf %.10Lf\\n", base, a_ruiseki[base], a);

  // return (b + exp_go) / a;
  return (b_ruiseki[base] + g_ruiseki[base]) / a_ruiseki[base];
}

long double solve() {
  long double ans = -1;

  init_dis();
  calc_exp_init();

  if (dis_go[st.y][st.x] != -1)
    ans = dis_go[st.y][st.x];

  int cnt = 0;

  for (int i = 2; i < (h - 2) * (w - 2); i++) {
    if (dis_sp[st.y][st.x] == -1 ||
        dis_go[st.y][st.x] != -1 &&
            dis_go[st.y][st.x] < dis_sp[st.y][st.x] + i) {
      break;
    }
    if (ans < -0.9)
      ans = calc_exp(i) + dis_sp[st.y][st.x];
    else
      ans = min(ans, calc_exp(i) + dis_sp[st.y][st.x]);
  }

  /*
  if(dis_sp[st.y][st.x] != -1){
    int le = 2, ri = dis_go[st.y][st.x] - dis_sp[st.y][st.x] + 1, mid1, mid2;
    long double res0, res1, res2;
    if(dis_go[st.y][st.x] == -1) ri = (h-2) * (w-2);
    while(ri - le >= 4){
      mid1 = (le * 2 + ri) / 3;
      mid2 = (le + ri * 2) / 3;
      res0 = calc_exp(le) + dis_sp[st.y][st.x];
      res1 = calc_exp(mid1) + dis_sp[st.y][st.x];
      res2 = calc_exp(mid2) + dis_sp[st.y][st.x];
      if(mid2 - mid1 <= 1) break;
      if(res0 >= res1 - EPS && res1 >= res2 - EPS) le = mid1;
      else ri = mid2;
    }
    for(int i=le;i<le+5;i++) {
      if(dis_go[st.y][st.x] != -1 && dis_go[st.y][st.x] < dis_sp[st.y][st.x] +
  i) break; if(ans < -0.9) ans = calc_exp(i) + dis_sp[st.y][st.x]; else ans =
  min(ans, calc_exp(i) + dis_sp[st.y][st.x]);
    }
  }
  */

  return ans;
}

int main() {
  char c;
  while (cin >> w >> h) {
    v.clear();
    int cnt = 0;
    for (int i = 0; i < h; i++) {
      for (int j = 0; j < w; j++) {
        cin >> c;
        wall[i][j] = true;
        if (c == 's')
          st = P(j, i), wall[i][j] = false;
        else if (c == 'g')
          go = P(j, i);
        else if (c == '*')
          v.push_back(P(j, i)), cnt++;
        else if (c == '.')
          wall[i][j] = false;
      }
    }

    printf("%.12Lf\\n", solve());
  }
}

Error: TLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;

const double INF = 1e+12;
const int H = 500;
const int W = 500;
const int dy[4] = {-1, 0, 1, 0};
const int dx[4] = {0, -1, 0, 1};

struct P {
  int x, y;
  P(int x = 0, int y = 0) : x(x), y(y) {}
};

struct state {
  P p;
  int cnt;
  state(P p = P(), int cnt = 0) : p(p), cnt(cnt) {}
};

int w, h, dis_go[H][W], dis_sp[H][W];
double cnt_wall;
P st, go;
vector<P> v;
bool wall[H][W];

void init_dis() {
  queue<state> q;
  state u, u2;

  cnt_wall = 0;
  for (int i = 0; i < h; i++) {
    for (int j = 0; j < w; j++) {
      dis_go[i][j] = dis_sp[i][j] = -1;
      cnt_wall += !wall[i][j];
    }
  }

  for (q.push(state(go, 0)); !q.empty();) {
    u = q.front();
    q.pop();
    for (int i = 0; i < 4; i++) {
      u2 = state(P(u.p.x + dx[i], u.p.y + dy[i]), u.cnt + 1);
      if (!wall[u2.p.y][u2.p.x] &&
          (dis_go[u2.p.y][u2.p.x] == -1 || dis_go[u2.p.y][u2.p.x] > u2.cnt)) {
        dis_go[u2.p.y][u2.p.x] = u2.cnt;
        q.push(u2);
      }
    }
  }

  for (int i = 0; i < v.size(); i++) {
    for (q.push(state(v[i], 0)); !q.empty();) {
      u = q.front();
      q.pop();
      for (int j = 0; j < 4; j++) {
        u2 = state(P(u.p.x + dx[j], u.p.y + dy[j]), u.cnt + 1);
        if (!wall[u2.p.y][u2.p.x] &&
            (dis_sp[u2.p.y][u2.p.x] == -1 || dis_sp[u2.p.y][u2.p.x] > u2.cnt)) {
          dis_sp[u2.p.y][u2.p.x] = u2.cnt;
          q.push(u2);
        }
      }
    }
  }
}

double calc_exp(int base) {
  double a = 1.0, b = 0.0, exp_go = 0.0;

  for (int i = 1; i < h - 1; i++) {
    for (int j = 1; j < w - 1; j++) {
      if (!wall[i][j]) {
        if (dis_go[i][j] == -1 ||
            dis_sp[i][j] != -1 && dis_go[i][j] >= dis_sp[i][j] + base) {
          a -= 1.0 / cnt_wall;
          b += (double)dis_sp[i][j] / cnt_wall;
        } else {
          exp_go += (double)dis_go[i][j] / cnt_wall;
        }
      }
    }
  }

  return (b + exp_go) / a;
}

double solve() {
  double ans = INF;

  init_dis();

  if (dis_go[st.y][st.x] != -1)
    ans = dis_go[st.y][st.x];
  // cout << ans << ' ';

  // TLE??????????????¢?´¢
  for (int i = 2; i < (h - 2) * (w - 2); i++) {
    if (dis_sp[st.y][st.x] == -1 ||
        dis_go[st.y][st.x] != -1 &&
            dis_go[st.y][st.x] < dis_sp[st.y][st.x] + i) {
      break;
    }
    ans = min(ans, calc_exp(i) + dis_sp[st.y][st.x]);
  }

  return ans;
}

int main() {
  char c;
  while (cin >> w >> h) {
    v.clear();
    for (int i = 0; i < h; i++) {
      for (int j = 0; j < w; j++) {
        cin >> c;
        wall[i][j] = true;
        if (c == 's')
          st = P(j, i), wall[i][j] = false;
        else if (c == 'g')
          go = P(j, i);
        else if (c == '*')
          v.push_back(P(j, i));
        else if (c == '.')
          wall[i][j] = false;
      }
    }
    printf("%.12f\\n", solve());
  }
}