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

#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <stdio.h>
#include <vector>
typedef long long int ll;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000001
using namespace std;

int W, H, index[20][20], dp[20][20][1024],
    fin_state; // dp[row][col][??¶???] = ????°??????????
char table[20][21];

struct Info {
  Info() {
    row = 0;
    col = 0;
    state = 0;
    cost = 0;
  }

  Info(int arg_row, int arg_col, int arg_state, int arg_cost) {
    row = arg_row;
    col = arg_col;
    state = arg_state;
    cost = arg_cost;
  }
  int row, col, state, cost;
};

Info start;
int diff_row[4] = {-1, 0, 0, 1}, diff_col[4] = {0, -1, 1, 0}, target_count,
    next_state;

bool rangeCheck(int row, int col) {
  if (row >= 0 && row <= H - 1 && col >= 0 && col <= W - 1)
    return true;
  else {
    return false;
  }
}

int main() {

  int ans, next_row, next_col;
  queue<Info> Q;

  while (true) {
    scanf("%d %d", &W, &H);
    if (W == 0 && H == 0)
      break;

    target_count = 0;

    for (int i = 0; i < H; i++) {
      scanf("%s", table[i]);
      for (int k = 0; k < W; k++) {
        switch (table[i][k]) {
        case '.':
          // Do nothing
          break;
        case '*':
          index[i][k] = target_count;
          target_count++;
          break;
        case 'x':
          // Do nothing
          break;
        case 'o':
          start.row = i;
          start.col = k;
          start.state = 0;
          start.cost = 0;
          break;
        }
      }
    }

    for (int i = 0; i < H; i++) {
      for (int k = 0; k < W; k++) {
        for (int p = 0; p < pow(2, target_count); p++)
          dp[i][k][p] = BIG_NUM;
      }
    }

    fin_state = pow(2, target_count) - 1;

    while (!Q.empty())
      Q.pop();

    ans = BIG_NUM;

    dp[start.row][start.col][0] = 0;
    Q.push(start);

    while (!Q.empty()) {

      if (Q.front().state == fin_state) {
        ans = Q.front().cost;
        break;
      }

      if (Q.front().cost != dp[Q.front().row][Q.front().col][Q.front().state]) {
        Q.pop();
        continue;
      } else {

        for (int i = 0; i < 4; i++) {
          next_row = Q.front().row + diff_row[i];
          next_col = Q.front().col + diff_col[i];

          if (rangeCheck(next_row, next_col) == false ||
              table[next_row][next_col] == 'x')
            continue;

          if (table[next_row][next_col] == '.' ||
              table[next_row][next_col] == 'o') {
            if (dp[Q.front().row][Q.front().col][Q.front().state] + 1 <
                dp[next_row][next_col][Q.front().state]) {
              dp[next_row][next_col][Q.front().state] =
                  dp[Q.front().row][Q.front().col][Q.front().state] + 1;
              Q.push(Info(next_row, next_col, Q.front().state,
                          dp[next_row][next_col][Q.front().state]));
            }
          } else {

            if (Q.front().state & (1 << index[next_row][next_col])) {

              if (dp[Q.front().row][Q.front().col][Q.front().state] + 1 <
                  dp[next_row][next_col][Q.front().state]) {
                dp[next_row][next_col][Q.front().state] =
                    dp[Q.front().row][Q.front().col][Q.front().state] + 1;
                Q.push(Info(next_row, next_col, Q.front().state,
                            dp[next_row][next_col][Q.front().state]));
              }

            } else {
              next_state = Q.front().state + pow(2, index[next_row][next_col]);
              if (dp[Q.front().row][Q.front().col][Q.front().state] + 1 <
                  dp[next_row][next_col][next_state]) {
                dp[next_row][next_col][next_state] =
                    dp[Q.front().row][Q.front().col][Q.front().state] + 1;
                Q.push(Info(next_row, next_col, next_state,
                            dp[next_row][next_col][next_state]));
              }
            }
          }
        }
        Q.pop();
      }
    }

    if (ans == BIG_NUM)
      printf("-1\\n");
    else {
      printf("%d\\n", ans);
    }
  }

  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <stdio.h>
#include <vector>
typedef long long int ll;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000001
using namespace std;

int W, H, min_cost[20][20], work[20][20], dp[11][10][1024]; // dp[??????????????´??????][????????°???????????´???][??¶???]
                                                            // = ????°??????????
char table[20][21];

struct Info {
  Info() {
    row = 0;
    col = 0;
  }

  Info(int arg_row, int arg_col) {
    row = arg_row;
    col = arg_col;
  }
  int row, col;
};

Info Target[10], start, target_start, target_goal;
int diff_row[4] = {-1, 0, 0, 1}, diff_col[4] = {0, -1, 1, 0},
    min_distance[10][10], target_count, from_start_min_distance[10], next_state;

bool rangeCheck(int row, int col) {
  if (row >= 0 && row <= H - 1 && col >= 0 && col <= W - 1)
    return true;
  else {
    return false;
  }
}

//????????????????????¢??§????????????????????¢??°
void enable_check(int row, int col) {
  for (int i = 0; i < 4; i++) {
    if (rangeCheck(row + diff_row[i], col + diff_col[i]) == true &&
        min_cost[row + diff_row[i]][col + diff_col[i]] > min_cost[row][col] &&
        table[row + diff_row[i]][col + diff_col[i]] !=
            'x') { //???????????§???????????£???????????????????????????????§??????????????????????????????????????????§??????
      min_cost[row + diff_row[i]][col + diff_col[i]] = min_cost[row][col] + 1;
      enable_check(row + diff_row[i], col + diff_col[i]);
    }
  }
}

void calc_min_distance(int row, int col) {
  for (int i = 0; i < 4; i++) {
    if (rangeCheck(row + diff_row[i], col + diff_col[i]) == true &&
        work[row + diff_row[i]][col + diff_col[i]] > work[row][col] &&
        table[row + diff_row[i]][col + diff_col[i]] !=
            'x') { //???????????§???????????£???????????????????????????????§??????????????????????????????????????????§??????
      work[row + diff_row[i]][col + diff_col[i]] = work[row][col] + 1;
      calc_min_distance(row + diff_row[i], col + diff_col[i]);
    }
  }
}

int main() {

  bool FLG;
  int ans, tmp;

  while (true) {
    scanf("%d %d", &W, &H);
    if (W == 0 && H == 0)
      break;

    for (int i = 0; i < H; i++) {
      for (int k = 0; k < W; k++) {
        min_cost[i][k] = BIG_NUM;
      }
    }

    target_count = 0;

    //?????±???????????????
    for (int i = 0; i < H; i++) {
      scanf("%s", table[i]);
      for (int k = 0; k < W; k++) {
        switch (table[i][k]) {
        case '.':
          // Do nothing
          break;
        case '*': //?±??????????
          Target[target_count].row = i;
          Target[target_count].col = k;
          target_count++;
          break;
        case 'x': //?????????
          // Do nothing
          break;
        case 'o': //??????????????°???
          start.row = i;
          start.col = k;
          break;
        }
      }
    }

    FLG = true;

    //???????????´????????§?????????????????????
    min_cost[start.row][start.col] = 0;
    enable_check(start.row, start.col);

    for (int i = 0; i < target_count; i++) {
      if (min_cost[Target[i].row][Target[i].col] ==
          BIG_NUM) { // start????????°?????§????????´???????????£????????¢??????
        FLG = false;
        break;
      }
    }

    if (!FLG) {
      printf("-1\\n");
      continue;
    }

    //???????????????????????°?????????????????¢????¨????
    for (int i = 0; i < target_count; i++) {
      from_start_min_distance[i] = min_cost[Target[i].row][Target[i].col];
    }

    //?¬??????´???????£???????????????¢????¨??????????
    for (int i = 0; i < target_count; i++) {
      for (int k = 0; k < target_count; k++)
        min_distance[i][k] = BIG_NUM;
    }

    for (int i = 0; i < target_count; i++) {
      target_start = Target[i]; //??????????????°????????????????¨????

      for (int k = 0; k < H; k++) {
        for (int p = 0; p < W; p++)
          work[k][p] = BIG_NUM;
      }

      work[target_start.row][target_start.col] = 0;
      calc_min_distance(target_start.row, target_start.col);

      for (int k = 0; k < target_count; k++) {
        min_distance[i][k] =
            min(min_distance[i][k], work[Target[k].row][Target[k].col]);
      }
    }

    // BIt_DP??§???????????¢????±???????
    for (int i = 1; i <= target_count; i++) {
      for (int k = 0; k < target_count; k++) {
        for (int p = 0; p < pow(2, target_count); p++)
          dp[i][k][p] = BIG_NUM;
      }
    }

    //?????????start?????????????????´??????????????¢????¨????
    //dp[??????????????´??????][????????°???????????´???][??¶???] =
    //????°??????????
    for (int i = 0; i < target_count; i++) {
      tmp = pow(2, i);
      dp[1][i][tmp] = from_start_min_distance[i];
    }

    for (int i = 2; i <= target_count;
         i++) { //??????????????´??????????????????
      for (int k = 0; k < target_count;
           k++) { //???????????´????????´???????????????
        for (int state = 0; state < pow(2, target_count);
             state++) { //??¶???????????????
          if (dp[i - 1][k][state] == BIG_NUM)
            continue;
          for (int a = 0; a < target_count; a++) { //?????????????????????
            if (state & (1 << a)) {
              //??¢???????????´??????????????????????????´?????????????????????
            } else {
              next_state = state + pow(2, a);
              dp[i][a][next_state] =
                  min(dp[i][a][next_state],
                      dp[i - 1][k][state] + min_distance[k][a]);
            }
          }
        }
      }
    }

    ans = BIG_NUM;
    tmp = pow(2, target_count) - 1;

    for (int i = 0; i < target_count; i++) {
      ans = min(ans, dp[target_count][i][tmp]);
    }

    printf("%d\\n", ans);
  }
  return 0;
}