Problem p00504 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <valarray>
#include <vector>
using namespace std;

#define REP(i, n) for (int i = 0; i < (int)n; ++i)
#define FOR(i, c)                                                              \
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)
#define ALL(c) (c).begin(), (c).end()
#define chmax(a, b) (a < (b) ? (a = b, 1) : 0)
#define chmin(a, b) (a > (b) ? (a = b, 1) : 0)
#define valid(y, x, h, w) (0 <= y && y < h && 0 <= x && x < w)
const int INF = 1 << 29;
const double EPS = 1e-8;
const double PI = acos(-1);
typedef pair<int, int> pii;
typedef long long ll;

char a[50][50];
int dp[50][50][4][1 << 11];
int bitMap[4][1 << 11][4];
bool canGet[4][1 << 11][4];
vector<pii> needCells[4];

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

int h, w, K;

int solve(int y, int x, int k, int S) {
  int &r = dp[y][x][k][S];
  if (r >= 0)
    return r;
  int res = -INF;
  if (y == h - 1 && x == w - 1)
    res = 0;
  REP(d, 4) {
    int nk = k + (d >= 2);
    if (nk > K)
      continue;
    int ny = y + dy[d];
    int nx = x + dx[d];
    if (!valid(ny, nx, h, w))
      continue;
    if (a[ny][nx] == '#')
      continue;
    int score = canGet[k][S][d] && isdigit(a[ny][nx]) ? a[ny][nx] - '0' : 0;
    chmax(res, solve(ny, nx, nk, bitMap[k][S][d]) + score);
  }
  // cout << y << " " << x << " " << k << " ";
  // REP(i,needCells[k].size()) {
  //   if (S>>i&1) {
  //     pii p = needCells[k][i];
  //     cout << "(" << p.first << "," << p.second << ")";
  //   }
  // }
  // cout << " " << res << endl;
  return r = res;
}

int main() {
  REP(k, 4) {
    for (int y = -3; y <= 3; ++y) {
      for (int x = -3; x <= 3; ++x) {
        if ((y || x) && -min(y, 0) - min(x, 0) <= 3 - k &&
            max(0, y) + max(0, x) <= k)
          needCells[k].push_back(pii(y, x));
      }
    }
  }
  REP(k, 4) {
    int n = needCells[k].size();
    REP(S, 1 << n) {
      REP(d, 4) {
        int nk = k + (d >= 2);
        if (nk == 4)
          continue;
        int T = 0;
        REP(i, n) {
          if (S >> i & 1) {
            pii p = needCells[k][i];
            p.first -= dy[d];
            p.second -= dx[d];
            REP(j, needCells[nk].size()) {
              if (needCells[nk][j] == p) {
                T |= 1 << j;
              }
            }
          }
        }
        REP(j, needCells[nk].size()) {
          if (needCells[nk][j] == pii(-dy[d], -dx[d])) {
            T |= 1 << j;
          }
        }
        bitMap[k][S][d] = T;

        canGet[k][S][d] = 1;
        REP(i, n)
        if (S >> i & 1 && needCells[k][i] == pii(dy[d], dx[d]))
          canGet[k][S][d] = 0;
      }
    }
  }
  while (cin >> h >> w >> K) {
    REP(i, h) REP(j, w) cin >> a[i][j];
    memset(dp, -1, sizeof(dp));
    cout << solve(0, 0, 0, 0) << endl;
  }
}

Fixed submission:
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <valarray>
#include <vector>
using namespace std;

#define REP(i, n) for (int i = 0; i < (int)n; ++i)
#define FOR(i, c)                                                              \
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)
#define ALL(c) (c).begin(), (c).end()
#define chmax(a, b) (a < (b) ? (a = b, 1) : 0)
#define chmin(a, b) (a > (b) ? (a = b, 1) : 0)
#define valid(y, x, h, w) (0 <= y && y < h && 0 <= x && x < w)
const int INF = 1 << 29;
const double EPS = 1e-8;
const double PI = acos(-1);
typedef pair<int, int> pii;
typedef long long ll;

char a[50][50];
int dp[50][50][4][1 << 11];
int bitMap[4][1 << 11][4];
bool canGet[4][1 << 11][4];
vector<pii> needCells[4];

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

int h, w, K;

int solve(int y, int x, int k, int S) {
  int &r = dp[y][x][k][S];
  if (r != -1)
    return r;
  int res = -INF;
  if (y == h - 1 && x == w - 1)
    res = 0;
  REP(d, 4) {
    int nk = k + (d >= 2);
    if (nk > K)
      continue;
    int ny = y + dy[d];
    int nx = x + dx[d];
    if (!valid(ny, nx, h, w))
      continue;
    if (a[ny][nx] == '#')
      continue;
    int score = canGet[k][S][d] && isdigit(a[ny][nx]) ? a[ny][nx] - '0' : 0;
    chmax(res, solve(ny, nx, nk, bitMap[k][S][d]) + score);
  }
  // cout << y << " " << x << " " << k << " ";
  // REP(i,needCells[k].size()) {
  //   if (S>>i&1) {
  //     pii p = needCells[k][i];
  //     cout << "(" << p.first << "," << p.second << ")";
  //   }
  // }
  // cout << " " << res << endl;
  return r = res;
}

int main() {
  REP(k, 4) {
    for (int y = -3; y <= 3; ++y) {
      for (int x = -3; x <= 3; ++x) {
        if ((y || x) && -min(y, 0) - min(x, 0) <= 3 - k &&
            max(0, y) + max(0, x) <= k)
          needCells[k].push_back(pii(y, x));
      }
    }
  }
  REP(k, 4) {
    int n = needCells[k].size();
    REP(S, 1 << n) {
      REP(d, 4) {
        int nk = k + (d >= 2);
        if (nk == 4)
          continue;
        int T = 0;
        REP(i, n) {
          if (S >> i & 1) {
            pii p = needCells[k][i];
            p.first -= dy[d];
            p.second -= dx[d];
            REP(j, needCells[nk].size()) {
              if (needCells[nk][j] == p) {
                T |= 1 << j;
              }
            }
          }
        }
        REP(j, needCells[nk].size()) {
          if (needCells[nk][j] == pii(-dy[d], -dx[d])) {
            T |= 1 << j;
          }
        }
        bitMap[k][S][d] = T;

        canGet[k][S][d] = 1;
        REP(i, n)
        if (S >> i & 1 && needCells[k][i] == pii(dy[d], dx[d]))
          canGet[k][S][d] = 0;
      }
    }
  }
  while (cin >> h >> w >> K) {
    REP(i, h) REP(j, w) cin >> a[i][j];
    memset(dp, -1, sizeof(dp));
    cout << solve(0, 0, 0, 0) << endl;
  }
}