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

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

#define MAX_H 20
#define MAX_W 20
#define MAX_G 10

const int dx[] = {0, 1, 0, -1};
const int dy[] = {1, 0, -1, 0};

struct S {
  int y, x, t;
  S(int y, int x, int t) : y(y), x(x), t(t) {}
};

#define INF (1 << 28)

string field[MAX_H];
int number[MAX_H][MAX_W];
int graph[MAX_G][MAX_G];
int dp[MAX_G][1 << MAX_G];
int h, w;
int garbage_count;

int solve(int v, int s) {
  if (dp[v][s] != INF)
    return dp[v][s];
  if (s == ((1 << garbage_count) - 1))
    return 0;
  int min_cost = INF;
  for (int i = 0; i < garbage_count; i++) {
    if (s & (1 << i))
      continue;
    min_cost = min(min_cost, solve(i, (s + (1 << i))) + graph[v][i]);
  }
  return dp[v][s] = min_cost;
}

int main() {
  while (cin >> w >> h) {
    if (w == 0 && h == 0)
      break;
    memset(graph, -1, sizeof(graph));
    memset(number, -1, sizeof(number));
    for (int i = 0; i < MAX_G; i++)
      for (int j = 0; j < (1 << MAX_G); j++)
        dp[i][j] = INF;
    for (int i = 0; i < h; i++)
      cin >> field[i];

    int cur = 1;
    for (int i = 0; i < h; i++)
      for (int j = 0; j < w; j++) {
        if (field[i][j] == 'o')
          number[i][j] = 0;
        if (field[i][j] == '*')
          number[i][j] = cur++;
      }
    garbage_count = cur;

    for (int i = 0; i < h; i++) {
      for (int j = 0; j < w; j++) {
        if (field[i][j] == 'o' || field[i][j] == '*') {
          bool visited[h][w];
          memset(visited, 0, sizeof(visited));
          queue<S> q;
          q.push(S(i, j, 0));
          visited[i][j] = true;
          int remain_garbage = garbage_count;
          while (!q.empty()) {
            S s = q.front();
            q.pop();
            if (field[s.y][s.x] == 'o' || field[s.y][s.x] == '*') {
              graph[number[i][j]][number[s.y][s.x]] = s.t;
              remain_garbage--;
              // if (remain_garbage == 0) break;
            }
            for (int k = 0; k < 4; k++) {
              int ny = s.y + dy[k];
              int nx = s.x + dx[k];
              if (0 <= ny && ny < h && 0 <= nx && nx < w && !visited[ny][nx] &&
                  field[ny][nx] != 'x') {
                visited[ny][nx] = true;
                q.push(S(ny, nx, s.t + 1));
              }
            }
          }
        }
      }
    }

    bool possible = true;
    for (int i = 0; i < garbage_count; i++)
      for (int j = 0; j < garbage_count; j++)
        if (graph[i][j] == -1) {
          possible = false;
          break;
        }

    //        for (int i = 0; i < garbage_count; i++) {
    //            for (int j = 0; j < garbage_count; j++) {
    //                cout << graph[i][j] << ' ';
    //            }
    //            cout << endl;
    //        }

    if (!possible)
      cout << -1 << endl;
    else
      cout << solve(0, 0) << endl;
  }
  return 0;
}

Error: MLE

Fixed submission:

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

#define MAX_H 20
#define MAX_W 20
#define MAX_G 10

const int dx[] = {0, 1, 0, -1};
const int dy[] = {1, 0, -1, 0};

struct S {
  int y, x, t;
  S(int y, int x, int t) : y(y), x(x), t(t) {}
};

#define INF (1 << 28)

string field[MAX_H];
int number[MAX_H][MAX_W];
int graph[MAX_G][MAX_G];
int dp[MAX_G][1 << MAX_G];
int h, w;
int garbage_count;

int solve(int v, int s) {
  if (dp[v][s] != INF)
    return dp[v][s];
  if (s == ((1 << garbage_count) - 1))
    return 0;
  int min_cost = INF;
  for (int i = 0; i < garbage_count; i++) {
    if (s & (1 << i))
      continue;
    min_cost = min(min_cost, solve(i, (s + (1 << i))) + graph[v][i]);
  }
  return dp[v][s] = min_cost;
}

int main() {
  while (cin >> w >> h) {
    if (w == 0 && h == 0)
      break;
    memset(graph, -1, sizeof(graph));
    memset(number, -1, sizeof(number));
    for (int i = 0; i < MAX_G; i++)
      for (int j = 0; j < (1 << MAX_G); j++)
        dp[i][j] = INF;
    for (int i = 0; i < h; i++)
      cin >> field[i];

    int cur = 1;
    for (int i = 0; i < h; i++)
      for (int j = 0; j < w; j++) {
        if (field[i][j] == 'o')
          number[i][j] = 0;
        if (field[i][j] == '*')
          number[i][j] = cur++;
      }
    garbage_count = cur;

    for (int i = 0; i < h; i++) {
      for (int j = 0; j < w; j++) {
        if (field[i][j] == 'o' || field[i][j] == '*') {
          bool visited[h][w];
          memset(visited, 0, sizeof(visited));
          queue<S> q;
          q.push(S(i, j, 0));
          while (!q.empty()) {
            S s = q.front();
            q.pop();
            visited[s.y][s.x] = true;
            if (field[s.y][s.x] == 'o' || field[s.y][s.x] == '*')
              graph[number[i][j]][number[s.y][s.x]] = s.t;
            for (int k = 0; k < 4; k++) {
              int ny = s.y + dy[k];
              int nx = s.x + dx[k];
              if (0 <= ny && ny < h && 0 <= nx && nx < w && !visited[ny][nx] &&
                  field[ny][nx] != 'x')
                q.push(S(ny, nx, s.t + 1));
            }
          }
        }
      }
    }

    bool possible = true;
    for (int i = 0; i < garbage_count; i++)
      for (int j = 0; j < garbage_count; j++)
        if (graph[i][j] == -1) {
          possible = false;
          break;
        }

    if (!possible)
      cout << -1 << endl;
    else
      cout << solve(0, 0) << endl;
  }
  return 0;
}