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

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;
#define REP(i, n) for (ll i = 0; i < (n); ++i)
#define RREP(i, n) for (ll i = (n)-1; i >= 0; --i)
#define ALL(v) (v).begin(), (v).end()
template <class T>
using reverse_priority_queue = priority_queue<T, vector<T>, greater<T>>;

mt19937 rng;
clock_t start;

const int D = 365;
const int NTYPE = 26;
array<int, NTYPE> c;
array<array<int, NTYPE>, D> s;

array<int, D> day_order;
array<int, NTYPE> type_order;

void input() {
  int _d;
  cin >> _d;
  REP(i, NTYPE) { cin >> c.at(i); }
  REP(i, D) {
    REP(j, NTYPE) { cin >> s.at(i).at(j); }
  }
}

void output(const array<int, D> &sch) {
  for (auto x : sch) {
    cout << x + 1 << endl;
  }
}

int calc_satisfaction(const array<int, D> &sch) {
  int ret = 0;
  array<int, NTYPE> last;
  fill(ALL(last), 0);
  REP(i, D) {
    const int cur_d = i + 1;
    const int t = sch.at(i);
    ret += s.at(i).at(t);
    last.at(t) = cur_d;
    REP(j, NTYPE) { ret -= c.at(j) * (cur_d - last.at(j)); }
  }
  return ret;
}

void greedy_init(array<int, D> &ans) {
  array<int, NTYPE> last;
  fill(ALL(last), 0);
  REP(i, D) {
    const int cur_d = i + 1;
    int max_type = -1;
    int max_val = numeric_limits<int>::min();
    REP(j, NTYPE) {
      int tmp = s.at(i).at(j) + c.at(j) * (cur_d - last.at(j));
      if (max_val < tmp) {
        max_type = j;
        max_val = tmp;
      }
    }
    assert(max_type != -1);
    ans.at(i) = max_type;
    last.at(max_type) = i + 1;
  }
}

void init() {
  REP(i, D) { day_order.at(i) = i; }
  REP(i, NTYPE) { type_order.at(i) = i; }
}

void solve() {
  rng.seed(0);
  array<int, D> ans;
  greedy_init(ans);

  uniform_real_distribution<> ur(0.0, 1.0);

  int cur_score = calc_satisfaction(ans);

  int best_score = cur_score;
  auto best_ans = ans;
  double temp = 2000;
  REP(i, 50) {
    bool modified = false;
    shuffle(ALL(day_order), rng);
    shuffle(ALL(type_order), rng);
    for (int j : day_order) {
      for (int k : type_order) {
        const int cur_k = ans.at(j);
        if (k == cur_k) {
          continue;
        }
        ans.at(j) = k;
        const int tmp = calc_satisfaction(ans);
        if (exp(-(double)(cur_score - tmp) / temp) >= ur(rng)) {
          cur_score = tmp;
          modified = true;
          if (cur_score > best_score) {
            best_score = cur_score;
            best_ans = ans;
          }
          break;
        } else {
          ans.at(j) = cur_k;
        }
      }
    }
    const double cur_sec = (double)(clock() - start) / CLOCKS_PER_SEC;
    if (!modified || cur_sec >= 1.9) {
      break;
    }
    temp *= 0.9;
  }
  output(best_ans);
}

int main() {
  start = clock();
  input();
  init();
  solve();
  return 0;
}


Error: TLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;
#define REP(i, n) for (ll i = 0; i < (n); ++i)
#define RREP(i, n) for (ll i = (n)-1; i >= 0; --i)
#define ALL(v) (v).begin(), (v).end()
template <class T>
using reverse_priority_queue = priority_queue<T, vector<T>, greater<T>>;

mt19937 rng;

const int D = 365;
const int NTYPE = 26;
array<int, NTYPE> c;
array<array<int, NTYPE>, D> s;

array<int, D> day_order;
array<int, NTYPE> type_order;

void input() {
  int _d;
  cin >> _d;
  REP(i, NTYPE) { cin >> c.at(i); }
  REP(i, D) {
    REP(j, NTYPE) { cin >> s.at(i).at(j); }
  }
}

void output(const array<int, D> &sch) {
  for (auto x : sch) {
    cout << x + 1 << endl;
  }
}

int calc_satisfaction(const array<int, D> &sch) {
  int ret = 0;
  array<int, NTYPE> last;
  fill(ALL(last), 0);
  REP(i, D) {
    const int cur_d = i + 1;
    const int t = sch.at(i);
    ret += s.at(i).at(t);
    last.at(t) = cur_d;
    REP(j, NTYPE) { ret -= c.at(j) * (cur_d - last.at(j)); }
  }
  return ret;
}

void greedy_init(array<int, D> &ans) {
  array<int, NTYPE> last;
  fill(ALL(last), 0);
  REP(i, D) {
    const int cur_d = i + 1;
    int max_type = -1;
    int max_val = numeric_limits<int>::min();
    REP(j, NTYPE) {
      int tmp = s.at(i).at(j) + c.at(j) * (cur_d - last.at(j));
      if (max_val < tmp) {
        max_type = j;
        max_val = tmp;
      }
    }
    assert(max_type != -1);
    ans.at(i) = max_type;
    last.at(max_type) = i + 1;
  }
}

void init() {
  REP(i, D) { day_order.at(i) = i; }
  REP(i, NTYPE) { type_order.at(i) = i; }
}

void solve() {
  rng.seed(0);
  array<int, D> ans;
  greedy_init(ans);

  uniform_real_distribution<> ur(0.0, 1.0);

  int cur_score = calc_satisfaction(ans);

  int best_score = cur_score;
  auto best_ans = ans;
  double temp = 2000;
  REP(i, 100) {
    bool modified = false;
    shuffle(ALL(day_order), rng);
    shuffle(ALL(type_order), rng);
    for (int j : day_order) {
      for (int k : type_order) {
        const int cur_k = ans.at(j);
        if (k == cur_k) {
          continue;
        }
        ans.at(j) = k;
        const int tmp = calc_satisfaction(ans);
        // cerr << cur_score << ' ' << tmp << ' ' << exp(- (double)(cur_score -
        // tmp) / temp) << endl;
        if (exp(-(double)(cur_score - tmp) / temp) >= ur(rng)) {
          cur_score = tmp;
          modified = true;
          if (cur_score > best_score) {
            best_score = cur_score;
            best_ans = ans;
          }
          break;
        } else {
          ans.at(j) = cur_k;
        }
      }
      // int best_k = ans.at(j);
      // int best_score = cur_score;
      // for(int k : type_order){
      //     if(ans.at(j) == k){ continue; }
      //     const int cur_k = ans.at(j);
      //     ans.at(j) = k;
      //     const int tmp = calc_satisfaction(ans);
      //     ans.at(j) = cur_k;
      //     if(tmp > best_score){
      //         best_k = k;
      //         best_score = tmp;
      //     }
      // }
      // if(best_k != ans.at(j)){
      //     modified = true;
      // }
      // ans.at(j) = best_k;
      // cur_score = best_score;
    }
    if (!modified) {
      // cerr << "break i=" << i << ' ' << best_score << endl;
      break;
    }
    temp *= 0.9;
  }
  output(best_ans);
}

int main() {
  input();
  init();
  solve();
  return 0;
}