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

#include <iostream>
#include <string>

using namespace std;

bool isCross(int l, int r) {
  if (l == 1 || l == 4 || l == 7)
    return false;
  if (l == 2 || l == 8)
    return (r == 1 || r == 4 || r == 7);
  return !(r == 3 || r == 6 || r == 9);
}

const int INF = 1 << 30;

int main() {
  for (string s; cin >> s, s != "#";) {
    int len = s.length();
    for (int i = 0; i < len; i++)
      s[i] -= '0';

    int memo[10][10][2], next[10][10][2];
    for (int l = 1; l < 10; l++)
      for (int r = 1; r < 10; r++)
        for (int b = 0; b < 2; b++) {
          memo[l][r][b] = (l == 5 || r == 5 || l == r) ? INF : 0;
        }
    for (int i = 0; i < len; i++) {
      int a = s[i];
      for (int l = 1; l < 10; l++)
        for (int r = 1; r < 10; r++)
          for (int b = 0; b < 2; b++) {
            next[l][r][b] = INF;
            if (l == 5 || r == 5 || l == r || (l != a && r != a) ||
                isCross(l, r))
              continue;
            else {
              if (l == a) {
                for (int bef = 1; bef < 10; bef++) {
                  if (bef != 5 && !isCross(bef, r)) {
                    next[a][r][0] = min(next[a][r][0], memo[bef][r][0] + 1);
                    next[a][r][0] = min(next[a][r][0], memo[bef][r][1]);
                  }
                }
              } else { // r==a
                for (int bef = 1; bef < 10; bef++) {
                  if (bef != 5 && !isCross(l, bef)) {
                    next[l][a][1] = min(next[l][a][1], memo[l][bef][0]);
                    next[l][a][1] = min(next[l][a][1], memo[l][bef][1] + 1);
                  }
                }
                if (r != a)
                  puts("exception");
              }
            }
          }

      for (int l = 1; l < 10; l++)
        for (int r = 1; r < 10; r++)
          for (int b = 0; b < 2; b++) { // update
            memo[l][r][b] = next[l][r][b];
          }
    }

    int ans = INF;
    for (int l = 1; l < 10; l++)
      for (int r = 1; r < 10; r++)
        for (int b = 0; b < 2; b++)
          ans = min(ans, memo[l][r][b]);
    cout << ans << endl;
  }

  return 0;
}

Error: MLE

Fixed submission:

#include <iostream>
#include <string>

using namespace std;

bool isCross(int l, int r) {
  if (l == 1 || l == 4 || l == 7)
    return false;
  if (l == 2 || l == 8)
    return (r == 1 || r == 4 || r == 7);
  return !(r == 3 || r == 6 || r == 9);
}

const int INF = 1 << 30;

int main() {
  for (string s; cin >> s, s != "#";) {
    int len = s.length();
    for (int i = 0; i < len; i++)
      s[i] -= '0';

    /* solution by Greedy Algorithm */
    /*		int lcnt=0;			// number of violations (use left foot in first
       step) bool lflg=false;	// whether should use left foot in next step
                    for(int i=1;i<len;i++){
                            if(lflg){
                                    if(isCross(s[i],s[i-1]))	lcnt++;
                                    else	lflg=!lflg;
                            }
                            else{
                                    if(isCross(s[i-1],s[i]))	lcnt++;
                                    else	lflg=!lflg;
                            }
                    }

                    int rcnt=0;			// number of violations (use right
       foot in first step) bool rflg=false;	// whether should use right foot
       in next step for(int i=1;i<len;i++){ if(rflg){ if(isCross(s[i-1],s[i]))
       rcnt++; else	rflg=!rflg;
                            }
                            else{
                                    if(isCross(s[i],s[i-1]))	rcnt++;
                                    else	rflg=!rflg;
                            }
                    }

                    cout<<min(lcnt,rcnt)<<endl;
    */
    /* solution by DP */
    static int memo[100001][10][10][2];
    for (int l = 1; l < 10; l++)
      for (int r = 1; r < 10; r++)
        for (int b = 0; b < 2; b++) {
          memo[0][l][r][b] = (l == 5 || r == 5 || l == r) ? INF : 0;
        }
    for (int i = 0; i < len; i++) {
      int a = s[i];
      for (int l = 1; l < 10; l++)
        for (int r = 1; r < 10; r++)
          for (int b = 0; b < 2; b++) {
            memo[i + 1][l][r][b] = INF;
            if (l == 5 || r == 5 || l == r || (l != a && r != a) ||
                isCross(l, r))
              continue;
            else {
              if (l == a) {
                for (int bef = 1; bef < 10; bef++) {
                  if (bef != 5 && !isCross(bef, r)) {
                    memo[i + 1][a][r][0] =
                        min(memo[i + 1][a][r][0], memo[i][bef][r][0] + 1);
                    memo[i + 1][a][r][0] =
                        min(memo[i + 1][a][r][0], memo[i][bef][r][1]);
                  }
                }
              } else { // r==a
                for (int bef = 1; bef < 10; bef++) {
                  if (bef != 5 && !isCross(l, bef)) {
                    memo[i + 1][l][a][1] =
                        min(memo[i + 1][l][a][1], memo[i][l][bef][0]);
                    memo[i + 1][l][a][1] =
                        min(memo[i + 1][l][a][1], memo[i][l][bef][1] + 1);
                  }
                }
                if (r != a)
                  puts("exception");
              }
            }
          }
    }

    int ans = INF;
    for (int l = 1; l < 10; l++)
      for (int r = 1; r < 10; r++)
        for (int b = 0; b < 2; b++)
          ans = min(ans, memo[len][l][r][b]);
    cout << ans << endl;
  }

  return 0;
}