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

#pragma GCC optimize("O3", "unroll-loops", "omit-frame-pointer",               \\
                     "inline") // Optimization flags
#pragma GCC option("arch=native", "tune=native", "no-zero-upper") // Enable AVX
#pragma GCC target("avx")                                         // Enable AVX
#include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (int(i) = (0); (i) < (int)(n); ++(i))
using ll = long long;
using P = pair<int, int>;
using namespace std;

#define INF ((1LL << 30) - 1)
#define LLINF (1LL << 60)
#define EPS (1e-10)

#define LIMIT_SEC 1.97

class Timer {
  chrono::high_resolution_clock::time_point start;

public:
  double limit;
  Timer() {
    start = chrono::high_resolution_clock::now();
    limit = LIMIT_SEC;
  }
  Timer(double limit) : limit(limit) {
    start = chrono::high_resolution_clock::now();
  }
  double get_time() {
    return chrono::duration<double>(chrono::high_resolution_clock::now() -
                                    start)
        .count();
  }
  bool time_over() {
    if (get_time() > limit) {
      return true;
    }
    return false;
  }
  void set_start() { start = chrono::high_resolution_clock::now(); }
  double get_limit() { return limit; }
};

Timer timer;

// 乱数器
class XorShift {
public:
  unsigned long x, y, z, w;
  XorShift() {
    x = 123456789;
    y = 362436069;
    z = 521288629;
    w = 88675123;
  }
  XorShift(unsigned long seed) {
    XorShift();
    w = seed;
    for (int i = 0; i < 100; ++i)
      (*this)();
  }
  unsigned long operator()() {
    unsigned long t = x ^ (x << 11);
    x = y;
    y = z;
    z = w;
    return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));
  }
};

XorShift rnd;

ll c[27];
ll s[366][27];

const int C = 26;

ll bestScore = 0;
ll lc[C];

ll csum[C][367];

vector<int> ans(365, 0);
vector<int> logc[C];

ll getScore() {
  ll ret = 0;
  for (int i = 0; i < C; ++i)
    lc[i] = 0;
  for (int d = 0; d < 365; ++d) {
    ret += s[d][ans[d]];
    lc[ans[d]] = d + 1;
    rep(i, C) { ret -= c[i] * ((d + 1) - lc[i]); }
  }
  return ret;
}

int main() {
  cin.tie(0);
  ios_base::sync_with_stdio(false);

  int D;
  cin >> D;
  rep(i, C) cin >> c[i];
  rep(i, D) rep(j, C) cin >> s[i][j];

  // 0日目は0
  // 増えて行くのは1日目から(0-index)
  for (int i = 0; i < C; ++i) {
    for (int d = 0; d < 366; ++d) {
      if (d == 0)
        continue;
      else {
        csum[i][d] += (csum[i][d - 1] + c[i]);
      }
    }
  }

  // makeGreedy
  rep(d, D) {
    int ma = 0, idx = 0;
    rep(i, C) {
      if (ma < s[d][i]) {
        ma = s[d][i];
        idx = i;
      }
    }
    ans[d] = idx;
    // logc[idx].push_back(d);
  }
  bestScore = getScore();
  vector<int> bestAns = ans;

  Timer timer;
  double startTime = timer.get_time();
  double nowTime = startTime;
  double startTemp = 50, endTemp = 10;
  double prevScore = bestScore;
  int cnt = 0;
  while (true) {
    ++cnt;
    nowTime = timer.get_time();
    if (nowTime - startTime > LIMIT_SEC)
      break;

    int d = rnd() % D;

    int change = rnd() % C;
    int prev = ans[d];
    ans[d] = change;

    ll tmp = getScore();

    double temp =
        startTemp + (endTemp - startTemp) * (nowTime - startTime) / LIMIT_SEC;
    double prob = exp((tmp - prevScore) / temp);

    if (tmp > bestScore or prob > (rnd() % INF) / (double)INF) {
      prevScore = tmp;
      if (tmp > bestScore) {
        bestScore = tmp;
        bestAns = ans;
      }
    } else {
      ans[d] = prev;
    }

    // if (tmp > bestScore) {
    //     //cerr << "Update: " << bestScore << endl;
    //     bestScore = tmp;
    //     bestAns = ans;
    // }
    // else {
    //     ans[d] = prev;
    // }
  }

  rep(i, D) cout << bestAns[i] + 1 << endl;
  cerr << bestScore << ", " << cnt << endl;
}

// 536769
// 548149


Error: TLE

Fixed submission:

#pragma GCC optimize("O3", "unroll-loops", "omit-frame-pointer",               \\
                     "inline") // Optimization flags
#pragma GCC option("arch=native", "tune=native", "no-zero-upper") // Enable AVX
#pragma GCC target("avx")                                         // Enable AVX
#include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (int(i) = (0); (i) < (int)(n); ++(i))
using ll = long long;
using P = pair<int, int>;
using namespace std;

#define INF ((1LL << 30) - 1)
#define LLINF (1LL << 60)
#define EPS (1e-10)

#define LIMIT_SEC 1.99

class Timer {
  chrono::high_resolution_clock::time_point start;

public:
  double limit;
  Timer() {
    start = chrono::high_resolution_clock::now();
    limit = LIMIT_SEC;
  }
  Timer(double limit) : limit(limit) {
    start = chrono::high_resolution_clock::now();
  }
  double get_time() {
    return chrono::duration<double>(chrono::high_resolution_clock::now() -
                                    start)
        .count();
  }
  bool time_over() {
    if (get_time() > limit) {
      return true;
    }
    return false;
  }
  void set_start() { start = chrono::high_resolution_clock::now(); }
  double get_limit() { return limit; }
};

Timer timer;

// 乱数器
class XorShift {
public:
  unsigned long x, y, z, w;
  XorShift() {
    x = 123456789;
    y = 362436069;
    z = 521288629;
    w = 88675123;
  }
  XorShift(unsigned long seed) {
    XorShift();
    w = seed;
    for (int i = 0; i < 100; ++i)
      (*this)();
  }
  unsigned long operator()() {
    unsigned long t = x ^ (x << 11);
    x = y;
    y = z;
    z = w;
    return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));
  }
};

XorShift rnd;

ll c[27];
ll s[366][27];

const int C = 26;

ll bestScore = 0;
ll lc[C];

ll csum[C][367];

vector<int> ans(365, 0);
vector<int> logc[C];

ll getScore() {
  ll ret = 0;
  for (int i = 0; i < C; ++i)
    lc[i] = 0;
  for (int d = 0; d < 365; ++d) {
    ret += s[d][ans[d]];
    lc[ans[d]] = d + 1;
    rep(i, C) { ret -= c[i] * ((d + 1) - lc[i]); }
  }
  return ret;
}

int main() {
  cin.tie(0);
  ios_base::sync_with_stdio(false);

  int D;
  cin >> D;
  rep(i, C) cin >> c[i];
  rep(i, D) rep(j, C) cin >> s[i][j];

  // 0日目は0
  // 増えて行くのは1日目から(0-index)
  for (int i = 0; i < C; ++i) {
    for (int d = 0; d < 366; ++d) {
      if (d == 0)
        continue;
      else {
        csum[i][d] += (csum[i][d - 1] + c[i]);
      }
    }
  }

  // makeGreedy
  rep(d, D) {
    int ma = 0, idx = 0;
    rep(i, C) {
      if (ma < s[d][i]) {
        ma = s[d][i];
        idx = i;
      }
    }
    ans[d] = idx;
    // logc[idx].push_back(d);
  }
  bestScore = getScore();
  vector<int> bestAns = ans;

  Timer timer;
  double startTime = timer.get_time();
  double nowTime = startTime;
  double startTemp = 50, endTemp = 10;
  double prevScore = bestScore;
  int cnt = 0;
  while (true) {
    ++cnt;
    nowTime = timer.get_time();
    if (nowTime - startTime > LIMIT_SEC)
      break;

    int d = rnd() % D;

    int change = rnd() % C;
    int prev = ans[d];
    ans[d] = change;

    ll tmp = getScore();

    double temp =
        startTemp + (endTemp - startTemp) * (nowTime - startTime) / LIMIT_SEC;
    double prob = exp((tmp - prevScore) / temp);

    if (tmp > bestScore or prob > (rnd() % INF) / (double)INF) {
      prevScore = tmp;
      if (tmp > bestScore) {
        bestScore = tmp;
        bestAns = ans;
      }
    } else {
      ans[d] = prev;
    }

    // if (tmp > bestScore) {
    //     //cerr << "Update: " << bestScore << endl;
    //     bestScore = tmp;
    //     bestAns = ans;
    // }
    // else {
    //     ans[d] = prev;
    // }
  }

  rep(i, D) cout << bestAns[i] + 1 << endl;
  cerr << bestScore << ", " << cnt << endl;
}

// 536769
// 548149