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

#include <algorithm>
#include <math.h>
#include <stdio.h>

using namespace std;

int minimum = -1;

int calcDiffSum(int table[4][4]) {
  int sum = 0;
  for (int row = 0; row < 4; row++) {
    for (int col = 0; col < 4; col++) {
      if (table[row][col] != 0) {
        sum += abs((table[row][col] - 1) / 4 - row) +
               abs((table[row][col] - 1) % 4 - col);
      }
    }
  }
  return sum;
}

int zeroLoc(int table[4][4]) {
  int zero_loc;
  for (int i = 0; i < 4; i++) {
    for (int k = 0; k < 4; k++) {
      if (table[i][k] == 0) {
        zero_loc = 10 * i + k;
      }
    }
  }
  return zero_loc;
}

void recursive(int table[4][4], int max_depth, int count, int pre_loc) {
  if (calcDiffSum(table) == 0) {
    minimum = max_depth;
    return;
  }

  if (minimum != -1)
    return;

  int next_table[4][4][4], tmp_loc, tmp_row, tmp_col, pre_row, pre_col;

  for (int a = 0; a < 4; a++) {
    for (int b = 0; b < 4; b++) {
      for (int c = 0; c < 4; c++) {
        next_table[a][b][c] = table[b][c];
      }
    }
  }
  tmp_loc = zeroLoc(table);
  switch (tmp_loc) {
  case 0:
    if (pre_loc != 1) {
      swap(next_table[0][0][0], next_table[0][0][1]);
      if (count < max_depth &&
          calcDiffSum(next_table[0]) <= max_depth - count) {
        recursive(next_table[0], max_depth, count + 1, tmp_loc);
      }
    }
    if (pre_loc != 10) {
      swap(next_table[1][0][0], next_table[1][1][0]);
      if (count < max_depth &&
          calcDiffSum(next_table[1]) <= max_depth - count) {
        recursive(next_table[1], max_depth, count + 1, tmp_loc);
      }
    }
    break;
  case 1:
  case 2:
    tmp_row = tmp_loc / 10, tmp_col = tmp_loc % 10;
    pre_row = pre_loc / 10, pre_col = pre_loc % 10;

    if (tmp_row != pre_row || tmp_col != pre_col + 1) {
      swap(next_table[0][tmp_row][tmp_col],
           next_table[0][tmp_row][tmp_col - 1]);
      if (count < max_depth &&
          calcDiffSum(next_table[0]) <= max_depth - count) {
        recursive(next_table[0], max_depth, count + 1, tmp_loc);
      }
    }

    if (tmp_row != pre_row - 1 || tmp_col != pre_col) {
      swap(next_table[1][tmp_row][tmp_col],
           next_table[1][tmp_row + 1][tmp_col]);
      if (count < max_depth &&
          calcDiffSum(next_table[1]) <= max_depth - count) {
        recursive(next_table[1], max_depth, count + 1, tmp_loc);
      }
    }

    if (tmp_row != pre_row || tmp_col != pre_col - 1) {
      swap(next_table[2][tmp_row][tmp_col],
           next_table[2][tmp_row][tmp_col + 1]);
      if (count < max_depth &&
          calcDiffSum(next_table[2]) <= max_depth - count) {
        recursive(next_table[2], max_depth, count + 1, tmp_loc);
      }
    }
    break;
  case 3:
    if (pre_loc != 2) {
      swap(next_table[0][0][3], next_table[0][0][2]);
      if (count < max_depth &&
          calcDiffSum(next_table[0]) <= max_depth - count) {
        recursive(next_table[0], max_depth, count + 1, tmp_loc);
      }
    }
    if (pre_loc != 13) {
      swap(next_table[1][0][3], next_table[1][1][3]);
      if (count < max_depth &&
          calcDiffSum(next_table[1]) <= max_depth - count) {
        recursive(next_table[1], max_depth, count + 1, tmp_loc);
      }
    }
    break;
  case 10:
  case 20:
    tmp_row = tmp_loc / 10, tmp_col = tmp_loc % 10;
    pre_row = pre_loc / 10, pre_col = pre_loc % 10;

    if (tmp_row != pre_row + 1 || tmp_col != pre_col) {
      swap(next_table[0][tmp_row][tmp_col],
           next_table[0][tmp_row - 1][tmp_col]);
      if (count < max_depth &&
          calcDiffSum(next_table[0]) <= max_depth - count) {
        recursive(next_table[0], max_depth, count + 1, tmp_loc);
      }
    }

    if (tmp_row != pre_row || tmp_col != pre_col - 1) {
      swap(next_table[1][tmp_row][tmp_col],
           next_table[1][tmp_row][tmp_col + 1]);
      if (count < max_depth &&
          calcDiffSum(next_table[1]) <= max_depth - count) {
        recursive(next_table[1], max_depth, count + 1, tmp_loc);
      }
    }

    if (tmp_row != pre_row - 1 || tmp_col != pre_col) {
      swap(next_table[2][tmp_row][tmp_col],
           next_table[2][tmp_row + 1][tmp_col]);
      if (count < max_depth &&
          calcDiffSum(next_table[2]) <= max_depth - count) {
        recursive(next_table[2], max_depth, count + 1, tmp_loc);
      }
    }
    break;
  case 11:
  case 12:
  case 21:
  case 22:
    tmp_row = tmp_loc / 10, tmp_col = tmp_loc % 10;
    pre_row = pre_loc / 10, pre_col = pre_loc % 10;

    if (tmp_row != pre_row || tmp_col != pre_col + 1) {
      swap(next_table[0][tmp_row][tmp_col],
           next_table[0][tmp_row][tmp_col - 1]);
      if (count < max_depth &&
          calcDiffSum(next_table[0]) <= max_depth - count) {
        recursive(next_table[0], max_depth, count + 1, tmp_loc);
      }
    }

    if (tmp_row != pre_row + 1 || tmp_col != pre_col) {
      swap(next_table[1][tmp_row][tmp_col],
           next_table[1][tmp_row - 1][tmp_col]);
      if (count < max_depth &&
          calcDiffSum(next_table[1]) <= max_depth - count) {
        recursive(next_table[1], max_depth, count + 1, tmp_loc);
      }
    }

    if (tmp_row != pre_row || tmp_col != pre_col - 1) {
      swap(next_table[2][tmp_row][tmp_col],
           next_table[2][tmp_row][tmp_col + 1]);
      if (count < max_depth &&
          calcDiffSum(next_table[2]) <= max_depth - count) {
        recursive(next_table[2], max_depth, count + 1, tmp_loc);
      }
    }

    if (tmp_row != pre_row - 1 || tmp_col != pre_col) {
      swap(next_table[3][tmp_row][tmp_col],
           next_table[3][tmp_row + 1][tmp_col]);
      if (count < max_depth &&
          calcDiffSum(next_table[3]) <= max_depth - count) {
        recursive(next_table[3], max_depth, count + 1, tmp_loc);
      }
    }
    break;
  case 13:
  case 23:
    tmp_row = tmp_loc / 10, tmp_col = tmp_loc % 10;
    pre_row = pre_loc / 10, pre_col = pre_loc % 10;

    if (tmp_row != pre_row + 1 || tmp_col != pre_col) {
      swap(next_table[0][tmp_row][tmp_col],
           next_table[0][tmp_row - 1][tmp_col]);
      if (count < max_depth &&
          calcDiffSum(next_table[0]) <= max_depth - count) {
        recursive(next_table[0], max_depth, count + 1, tmp_loc);
      }
    }

    if (tmp_row != pre_row || tmp_col != pre_col + 1) {
      swap(next_table[1][tmp_row][tmp_col],
           next_table[1][tmp_row][tmp_col - 1]);
      if (count < max_depth &&
          calcDiffSum(next_table[1]) <= max_depth - count) {
        recursive(next_table[1], max_depth, count + 1, tmp_loc);
      }
    }

    if (tmp_row != pre_row - 1 || tmp_col != pre_col) {
      swap(next_table[2][tmp_row][tmp_col],
           next_table[2][tmp_row + 1][tmp_col]);
      if (count < max_depth &&
          calcDiffSum(next_table[2]) <= max_depth - count) {
        recursive(next_table[2], max_depth, count + 1, tmp_loc);
      }
    }

    break;
  case 30:
    if (pre_loc != 20) {
      swap(next_table[0][3][0], next_table[0][2][0]);
      if (count < max_depth &&
          calcDiffSum(next_table[0]) <= max_depth - count) {
        recursive(next_table[0], max_depth, count + 1, tmp_loc);
      }
    }

    if (pre_loc != 31) {
      swap(next_table[1][3][0], next_table[1][3][1]);
      if (count < max_depth &&
          calcDiffSum(next_table[1]) <= max_depth - count) {
        recursive(next_table[1], max_depth, count + 1, tmp_loc);
      }
    }
    break;
  case 31:
  case 32:
    tmp_row = tmp_loc / 10, tmp_col = tmp_loc % 10;
    pre_row = pre_loc / 10, pre_col = pre_loc % 10;

    if (tmp_row != pre_row || tmp_col != pre_col + 1) {
      swap(next_table[0][tmp_row][tmp_col],
           next_table[0][tmp_row][tmp_col - 1]);
      if (count < max_depth &&
          calcDiffSum(next_table[0]) <= max_depth - count) {
        recursive(next_table[0], max_depth, count + 1, tmp_loc);
      }
    }

    if (tmp_row != pre_row + 1 || tmp_col != pre_col) {
      swap(next_table[1][tmp_row][tmp_col],
           next_table[1][tmp_row - 1][tmp_col]);
      if (count < max_depth &&
          calcDiffSum(next_table[1]) <= max_depth - count) {
        recursive(next_table[1], max_depth, count + 1, tmp_loc);
      }
    }

    if (tmp_row != pre_row || tmp_col != pre_col - 1) {
      swap(next_table[2][tmp_row][tmp_col],
           next_table[2][tmp_row][tmp_col + 1]);
      if (count < max_depth &&
          calcDiffSum(next_table[2]) <= max_depth - count) {
        recursive(next_table[2], max_depth, count + 1, tmp_loc);
      }
    }
    break;
  case 33:
    if (pre_loc != 23) {
      swap(next_table[0][3][3], next_table[0][2][3]);
      if (count < max_depth &&
          calcDiffSum(next_table[0]) <= max_depth - count) {
        recursive(next_table[0], max_depth, count + 1, tmp_loc);
      }
    }

    if (pre_loc != 32) {
      swap(next_table[1][3][3], next_table[1][3][2]);
      if (count < max_depth &&
          calcDiffSum(next_table[1]) <= max_depth - count) {
        recursive(next_table[1], max_depth, count + 1, tmp_loc);
      }
    }
    break;
  }
}

void func(int table[4][4], int max_depth) {
  while (minimum == -1 && max_depth <= 45) {
    recursive(table, max_depth, 0, -1);
    max_depth++;
  }
}

int main() {

  int table[4][4], start_count;

  for (int i = 0; i < 4; i++) {
    scanf("%d %d %d %d", &table[i][0], &table[i][1], &table[i][2],
          &table[i][3]);
  }
  start_count = calcDiffSum(table);

  func(table, start_count);

  printf("%d\\n", minimum);

  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <math.h>
#include <stdio.h>

using namespace std;

int minimum = -1;

int calcDiffSum(int table[4][4]) {
  int sum = 0;
  for (int row = 0; row < 4; row++) {
    for (int col = 0; col < 4; col++) {
      if (table[row][col] != 0) {
        sum += abs((table[row][col] - 1) / 4 - row) +
               abs((table[row][col] - 1) % 4 - col);
      }
    }
  }
  return sum;
}

int zeroLoc(int table[4][4]) {
  int zero_loc;
  for (int i = 0; i < 4; i++) {
    for (int k = 0; k < 4; k++) {
      if (table[i][k] == 0) {
        zero_loc = 10 * i + k;
      }
    }
  }
  return zero_loc;
}

void recursive(int table[4][4], int max_depth, int count) {
  if (calcDiffSum(table) == 0) {
    minimum = max_depth;
    return;
  }

  int next_table[4][4][4], tmp_loc, tmp_row, tmp_col;

  for (int a = 0; a < 4; a++) {
    for (int b = 0; b < 4; b++) {
      for (int c = 0; c < 4; c++) {
        next_table[a][b][c] = table[b][c];
      }
    }
  }
  tmp_loc = zeroLoc(table);
  switch (tmp_loc) {
  case 0:
    swap(next_table[0][0][0], next_table[0][0][1]);
    if (count < max_depth && calcDiffSum(next_table[0]) <= max_depth - count) {
      recursive(next_table[0], max_depth, count + 1);
    }

    swap(next_table[1][0][0], next_table[1][1][0]);
    if (count < max_depth && calcDiffSum(next_table[1]) <= max_depth - count) {
      recursive(next_table[1], max_depth, count + 1);
    }
    break;
  case 1:
  case 2:
    tmp_row = tmp_loc / 10, tmp_col = tmp_loc % 10;

    swap(next_table[0][tmp_row][tmp_col], next_table[0][tmp_row][tmp_col - 1]);
    if (count < max_depth && calcDiffSum(next_table[0]) <= max_depth - count) {
      recursive(next_table[0], max_depth, count + 1);
    }

    swap(next_table[1][tmp_row][tmp_col], next_table[1][tmp_row + 1][tmp_col]);
    if (count < max_depth && calcDiffSum(next_table[1]) <= max_depth - count) {
      recursive(next_table[1], max_depth, count + 1);
    }

    swap(next_table[2][tmp_row][tmp_col], next_table[2][tmp_row][tmp_col + 1]);
    if (count < max_depth && calcDiffSum(next_table[2]) <= max_depth - count) {
      recursive(next_table[2], max_depth, count + 1);
    }
    break;
  case 3:
    swap(next_table[0][0][3], next_table[0][0][2]);
    if (count < max_depth && calcDiffSum(next_table[0]) <= max_depth - count) {
      recursive(next_table[0], max_depth, count + 1);
    }

    swap(next_table[1][0][3], next_table[1][1][3]);
    if (count < max_depth && calcDiffSum(next_table[1]) <= max_depth - count) {
      recursive(next_table[1], max_depth, count + 1);
    }

    break;
  case 10:
  case 20:
    tmp_row = tmp_loc / 10, tmp_col = tmp_loc % 10;

    swap(next_table[0][tmp_row][tmp_col], next_table[0][tmp_row - 1][tmp_col]);
    if (count < max_depth && calcDiffSum(next_table[0]) <= max_depth - count) {
      recursive(next_table[0], max_depth, count + 1);
    }

    swap(next_table[1][tmp_row][tmp_col], next_table[1][tmp_row][tmp_col + 1]);
    if (count < max_depth && calcDiffSum(next_table[1]) <= max_depth - count) {
      recursive(next_table[1], max_depth, count + 1);
    }

    swap(next_table[2][tmp_row][tmp_col], next_table[2][tmp_row + 1][tmp_col]);
    if (count < max_depth && calcDiffSum(next_table[2]) <= max_depth - count) {
      recursive(next_table[2], max_depth, count + 1);
    }

    break;
  case 11:
  case 12:
  case 21:
  case 22:
    tmp_row = tmp_loc / 10, tmp_col = tmp_loc % 10;

    swap(next_table[0][tmp_row][tmp_col], next_table[0][tmp_row][tmp_col - 1]);
    if (count < max_depth && calcDiffSum(next_table[0]) <= max_depth - count) {
      recursive(next_table[0], max_depth, count + 1);
    }

    swap(next_table[1][tmp_row][tmp_col], next_table[1][tmp_row - 1][tmp_col]);
    if (count < max_depth && calcDiffSum(next_table[1]) <= max_depth - count) {
      recursive(next_table[1], max_depth, count + 1);
    }

    swap(next_table[2][tmp_row][tmp_col], next_table[2][tmp_row][tmp_col + 1]);
    if (count < max_depth && calcDiffSum(next_table[2]) <= max_depth - count) {
      recursive(next_table[2], max_depth, count + 1);
    }

    swap(next_table[3][tmp_row][tmp_col], next_table[3][tmp_row + 1][tmp_col]);
    if (count < max_depth && calcDiffSum(next_table[3]) <= max_depth - count) {
      recursive(next_table[3], max_depth, count + 1);
    }

    break;
  case 13:
  case 23:
    tmp_row = tmp_loc / 10, tmp_col = tmp_loc % 10;

    swap(next_table[0][tmp_row][tmp_col], next_table[0][tmp_row - 1][tmp_col]);
    if (count < max_depth && calcDiffSum(next_table[0]) <= max_depth - count) {
      recursive(next_table[0], max_depth, count + 1);
    }

    swap(next_table[1][tmp_row][tmp_col], next_table[1][tmp_row][tmp_col - 1]);
    if (count < max_depth && calcDiffSum(next_table[1]) <= max_depth - count) {
      recursive(next_table[1], max_depth, count + 1);
    }

    swap(next_table[2][tmp_row][tmp_col], next_table[2][tmp_row + 1][tmp_col]);
    if (count < max_depth && calcDiffSum(next_table[2]) <= max_depth - count) {
      recursive(next_table[2], max_depth, count + 1);
    }
    break;
  case 30:
    swap(next_table[0][3][0], next_table[0][2][0]);
    if (count < max_depth && calcDiffSum(next_table[0]) <= max_depth - count) {
      recursive(next_table[0], max_depth, count + 1);
    }

    swap(next_table[1][3][0], next_table[1][3][1]);
    if (count < max_depth && calcDiffSum(next_table[1]) <= max_depth - count) {
      recursive(next_table[1], max_depth, count + 1);
    }
    break;
  case 31:
  case 32:
    tmp_row = tmp_loc / 10, tmp_col = tmp_loc % 10;

    swap(next_table[0][tmp_row][tmp_col], next_table[0][tmp_row][tmp_col - 1]);
    if (count < max_depth && calcDiffSum(next_table[0]) <= max_depth - count) {
      recursive(next_table[0], max_depth, count + 1);
    }

    swap(next_table[1][tmp_row][tmp_col], next_table[1][tmp_row - 1][tmp_col]);
    if (count < max_depth && calcDiffSum(next_table[1]) <= max_depth - count) {
      recursive(next_table[1], max_depth, count + 1);
    }

    swap(next_table[2][tmp_row][tmp_col], next_table[2][tmp_row][tmp_col + 1]);
    if (count < max_depth && calcDiffSum(next_table[2]) <= max_depth - count) {
      recursive(next_table[2], max_depth, count + 1);
    }
    break;
  case 33:
    swap(next_table[0][3][3], next_table[0][2][3]);
    if (count < max_depth && calcDiffSum(next_table[0]) <= max_depth - count) {
      recursive(next_table[0], max_depth, count + 1);
    }

    swap(next_table[1][3][3], next_table[1][3][2]);
    if (count < max_depth && calcDiffSum(next_table[1]) <= max_depth - count) {
      recursive(next_table[1], max_depth, count + 1);
    }
    break;
  }
}

void func(int table[4][4], int max_depth) {
  while (minimum == -1 && max_depth <= 45) {
    recursive(table, max_depth, 0);
    max_depth++;
  }
}

int main() {

  int table[4][4], start_count;

  for (int i = 0; i < 4; i++) {
    scanf("%d %d %d %d", &table[i][0], &table[i][1], &table[i][2],
          &table[i][3]);
  }
  start_count = calcDiffSum(table);

  func(table, start_count);

  printf("%d\\n", minimum);

  return 0;
}