Problem p03330 (C++)

Buggy submission (status: Time Limit Exceeded):
#define _CRT_SECURE_NO_WARNINGS
#include <algorithm>
#include <cmath>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>

using namespace std;

typedef pair<int, int> P;
typedef long long ll;
#define PB push_back
#define rep(i, a) for (int i = 0; i < a; i++)
#define all(v) v.begin(), v.end()
#define FF first
#define SS second
#define mp make_pair
#define INT int_64
#define MOD 998244353
const ll INF = (1 << 30);
const ll NEGA = -INF * 10000;

// 階乗
ll Kaijou(ll a) {
  if (a < 2)
    return 1;
  return a * Kaijou(a - 1) % MOD;
}

// 逆元の計算用(pは素数のときb=p-2で逆元)
ll calc(ll a, ll b, ll p) {
  if (b == 0)
    return 1;
  if (b % 2 == 0) {
    ll d = calc(a, b / 2, p);
    return (d * d) % p;
  } else {
    return (a * calc(a, b - 1, p)) % p;
  }
}

// ユークリッドの互除法
ll gcd(ll x, ll y) {
  if (x < y)
    swap(x, y);
  if (y == 0)
    return x;
  return gcd(y, x % y);
}

ll CCC(ll all, ll a, ll b, ll c) {
  all = Kaijou(all) % MOD;
  a = Kaijou(a);
  b = Kaijou(b);
  c = Kaijou(c);
  ll sita = ((a * b) % MOD * c) % MOD;
  return all * calc(sita, MOD - 2, MOD) % MOD;
}

ll ans = INF;

ll cc[501][501];
ll D[31][31];

ll pdmin[3];

int main() {

  ll n, c;
  cin >> n >> c;
  rep(i, c) rep(j, c) { cin >> D[i][j]; }
  rep(i, n) rep(j, n) cin >> cc[i][j];

  rep(k, 3) { pdmin[k] = INF; }

  ll pd[3] = {0};
  rep(m, c * c * c) {
    ll mm[3] = {0};
    mm[0] = m % c;
    mm[1] = (m / c) % c;
    mm[2] = (m / c) / c;
    if (mm[0] == mm[1] || mm[1] == mm[2] || mm[2] == mm[0])
      continue;
    rep(k, 3) {
      pd[k] = 0;
      rep(i, n) rep(j, n) {
        if ((i + j) % 3 == k)
          pd[k] += D[cc[i][j] - 1][mm[k]];
      }
    }
    ans = min(ans, pd[0] + pd[1] + pd[2]);
  }

  cout << ans << endl;
}

Fixed submission:
#define _CRT_SECURE_NO_WARNINGS
#include <algorithm>
#include <cmath>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>

using namespace std;

typedef pair<int, int> P;
typedef long long ll;
#define PB push_back
#define rep(i, a) for (int i = 0; i < a; i++)
#define all(v) v.begin(), v.end()
#define FF first
#define SS second
#define mp make_pair
#define INT int_64
#define MOD 998244353
const ll INF = (1 << 30);
const ll NEGA = -INF * 10000;

// 階乗
ll Kaijou(ll a) {
  if (a < 2)
    return 1;
  return a * Kaijou(a - 1) % MOD;
}

// 逆元の計算用(pは素数のときb=p-2で逆元)
ll calc(ll a, ll b, ll p) {
  if (b == 0)
    return 1;
  if (b % 2 == 0) {
    ll d = calc(a, b / 2, p);
    return (d * d) % p;
  } else {
    return (a * calc(a, b - 1, p)) % p;
  }
}

// ユークリッドの互除法
ll gcd(ll x, ll y) {
  if (x < y)
    swap(x, y);
  if (y == 0)
    return x;
  return gcd(y, x % y);
}

ll CCC(ll all, ll a, ll b, ll c) {
  all = Kaijou(all) % MOD;
  a = Kaijou(a);
  b = Kaijou(b);
  c = Kaijou(c);
  ll sita = ((a * b) % MOD * c) % MOD;
  return all * calc(sita, MOD - 2, MOD) % MOD;
}

ll ans = INF;

ll cc[501][501];
ll D[31][31];

ll pdmin[3];

int main() {

  ll n, c;
  cin >> n >> c;
  rep(i, c) rep(j, c) { cin >> D[i][j]; }
  rep(i, n) rep(j, n) cin >> cc[i][j];

  rep(k, 3) { pdmin[k] = INF; }

  ll pd[3] = {0};
  ll used[3] = {-1, -1, -1};
  rep(k, 3) {
    rep(m, c) {
      pd[k] = 0;
      rep(i, n) rep(j, n) {
        if ((i + j) % 3 == k)
          pd[k] += D[cc[i][j] - 1][m];
      }
      if (pdmin[k] >= pd[k] && used[0] != m && used[1] != m && used[2] != m) {
        used[k] = m;
        pdmin[k] = pd[k];
      }
    }
  }
  ans = min(ans, pdmin[0] + pdmin[1] + pdmin[2]);
  rep(k, 3) { pdmin[k] = INF; }
  used[2] = used[1] = used[0] = -1;
  rep(k, 3) {
    rep(m, c) {
      pd[(k + 1) % 3] = 0;
      rep(i, n) rep(j, n) {
        if ((i + j) % 3 == k)
          pd[(k + 1) % 3] += D[cc[i][j] - 1][m];
      }
      if (pdmin[(k + 1) % 3] >= pd[(k + 1) % 3] && used[0] != m &&
          used[1] != m && used[2] != m) {
        used[(k + 1) % 3] = m;
        pdmin[(k + 1) % 3] = pd[(k + 1) % 3];
      }
    }
  }
  ans = min(ans, pdmin[0] + pdmin[1] + pdmin[2]);
  rep(k, 3) { pdmin[k] = INF; }
  used[2] = used[1] = used[0] = -1;
  rep(k, 3) {
    rep(m, c) {
      pd[(k + 2) % 3] = 0;
      rep(i, n) rep(j, n) {
        if ((i + j) % 3 == k)
          pd[(k + 2) % 3] += D[cc[i][j] - 1][m];
      }
      if (pdmin[(k + 2) % 3] >= pd[(k + 2) % 3] && used[0] != m &&
          used[1] != m && used[2] != m) {
        used[(k + 2) % 3] = m;
        pdmin[(k + 2) % 3] = pd[(k + 2) % 3];
      }
    }
  }
  ans = min(ans, pdmin[0] + pdmin[1] + pdmin[2]);
  rep(k, 3) { pdmin[k] = INF; }
  int cnt = 0;
  used[2] = used[1] = used[0] = -1;
  while (cnt < 3) {
    int k;
    if (cnt == 0)
      k = 0;
    if (cnt == 1)
      k = 2;
    if (cnt == 2)
      k = 1;
    rep(m, c) {
      pd[k] = 0;
      rep(i, n) rep(j, n) {
        if ((i + j) % 3 == k)
          pd[k] += D[cc[i][j] - 1][m];
      }
      if (pdmin[k] >= pd[k] && used[0] != m && used[1] != m && used[2] != m) {
        used[k] = m;
        pdmin[k] = pd[k];
      }
    }
    cnt++;
  }
  ans = min(ans, pdmin[0] + pdmin[1] + pdmin[2]);

  rep(k, 3) { pdmin[k] = INF; }
  cnt = 0;
  used[2] = used[1] = used[0] = -1;
  while (cnt < 3) {
    int k;
    if (cnt == 0)
      k = 1;
    if (cnt == 1)
      k = 0;
    if (cnt == 2)
      k = 2;
    rep(m, c) {
      pd[k] = 0;
      rep(i, n) rep(j, n) {
        if ((i + j) % 3 == k)
          pd[k] += D[cc[i][j] - 1][m];
      }
      if (pdmin[k] >= pd[k] && used[0] != m && used[1] != m && used[2] != m) {
        used[k] = m;
        pdmin[k] = pd[k];
      }
    }
    cnt++;
  }
  ans = min(ans, pdmin[0] + pdmin[1] + pdmin[2]);
  rep(k, 3) { pdmin[k] = INF; }
  cnt = 0;
  used[2] = used[1] = used[0] = -1;
  while (cnt < 3) {
    int k;
    if (cnt == 0)
      k = 2;
    if (cnt == 1)
      k = 1;
    if (cnt == 2)
      k = 0;
    rep(m, c) {
      pd[k] = 0;
      rep(i, n) rep(j, n) {
        if ((i + j) % 3 == k)
          pd[k] += D[cc[i][j] - 1][m];
      }
      if (pdmin[k] >= pd[k] && used[0] != m && used[1] != m && used[2] != m) {
        used[k] = m;
        pdmin[k] = pd[k];
      }
    }
    cnt++;
  }
  ans = min(ans, pdmin[0] + pdmin[1] + pdmin[2]);

  cout << ans << endl;
}