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

#include <algorithm>
#include <array>
#include <bitset>
#include <chrono>
#include <cmath>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

#include <cstring>

using namespace std;

using ll = long long;
using ull = unsigned long long;
ll const MM = 1000000007;
// ll const NN = 1000000007;

#define pv(val) cerr << #val << '=' << (val) << endl
#define pl cerr << '@' << __LINE__ << endl

#define rep(i, n) for (ll i = 0; i < (n); i++)
#define rep2(i, b, e) for (ll i = (b); i < (e); i++)
#define all(a) a.begin(), a.end()
#define rall(a) a.rbegin(), a.rend()

template <class T> ostream &operator<<(ostream &os, vector<T> const &vec);
template <class T, size_t S>
ostream &operator<<(ostream &os, array<T, S> const &arr);
template <class T, class U>
ostream &operator<<(ostream &os, pair<T, U> const &p);
template <class... Args>
ostream &operator<<(ostream &os, tuple<Args...> const &t);

template <class T> ostream &operator<<(ostream &os, vector<T> const &vec) {
  if (vec.empty()) {
    os << "{}";
  } else {
    os << '{';
    for (size_t i = 0; i < vec.size() - 1; i++)
      os << vec[i] << ", ";
    os << vec.back() << '}';
  }
  return os;
}

template <class T, size_t S>
ostream &operator<<(ostream &os, array<T, S> const &arr) {
  if (arr.empty()) {
    os << "{}";
  } else {
    os << '{';
    for (size_t i = 0; i < arr.size() - 1; i++)
      os << arr[i] << ", ";
    os << arr.back() << '}';
  }
  return os;
}

template <class T, class U>
ostream &operator<<(ostream &os, pair<T, U> const &p) {
  os << '(' << p.first << ", " << p.second << ')';
  return os;
}

template <size_t I, class... Args>
typename enable_if<sizeof...(Args) == (I + 1)>::type
print_tuple(ostream &os, tuple<Args...> const &t) {
  os << get<I>(t);
}
template <size_t I, class... Args>
typename enable_if<sizeof...(Args) != (I + 1)>::type
print_tuple(ostream &os, tuple<Args...> const &t) {
  os << get<I>(t) << ", ";
  print_tuple<I + 1, Args...>(os, t);
}

template <class... Args>
ostream &operator<<(ostream &os, tuple<Args...> const &t) {
  os << '(';
  print_tuple<0, Args...>(os, t);
  os << ')';

  return os;
}

struct Timer {
  using Clock = std::chrono::system_clock;
  Clock::time_point startTime;

  Timer() { start(); }
  void start() { startTime = Clock::now(); }

  long long milli() const {
    return std::chrono::duration_cast<std::chrono::milliseconds>(Clock::now() -
                                                                 startTime)
        .count();
  }
  long long micro() const {
    return std::chrono::duration_cast<std::chrono::microseconds>(Clock::now() -
                                                                 startTime)
        .count();
  }
};

ll bound(function<bool(ll)> f, ll ng, ll ok) {
  while (abs(ng - ok) > 1) {
    ll mid = (ng + ok) / 2;
    if (f(mid))
      ok = mid;
    else
      ng = mid;
  }

  return ok;
}

ll order(vector<ll> const &r) {
  vector<ll> a(r.size());
  iota(all(a), 1);

  ll ord = 0;
  while (a != r) {
    next_permutation(all(a));
    ord++;
  }

  return ord;
}

ll div(ll n) {
  ll ans = 0;
  while (n > 0) {
    ans++;
    n /= 2;
  }

  return ans;
}

// value, weight
ll knapsack(vector<pair<ll, ll>> const &a, ll max_w) {
  ll max_n = a.size();
  vector<ll> table(max_w + 1, 0);

  for (int i = 1; i <= max_n; ++i) {
    ll v = a[i].first;
    ll w = a[i].second;
    if (w <= max_w && table[w] < v)
      table[w] = v;
    for (int j = 1; j <= max_w - w; j++) {
      if (table[j] != 0 && table[w + j] < table[j] + v)
        table[w + j] = table[j] + v;
    }
  }

  return *max_element(all(table));
}

ll llpow(ll n, ll m) {
  ll ans = 1;
  rep(i, m) {
    ans *= n;
    ans %= MM;
  }

  return ans;
}

Timer gTimer;

ll D;
array<ll, 26> c;
array<array<ll, 26>, 365> s;
ll score(array<ll, 365> const &ans) {
  ll sc = 0;
  array<ll, 26> last = {};
  rep(d, 365) {
    last[ans[d]] = d + 1;
    rep(i, 26) sc -= c[i] * (d + 1 - last[i]);
    sc += s[d][ans[d]];
  }

  return sc;
}

ll scoreDiff(array<ll, 365> const &ans, ll i) {
  ll sc = 0;
  ll last = 0;
  rep(d, 365) {
    if (ans[d] == i) {
      last = d + 1;
      sc += s[d][i];
    }
    sc -= c[i] * (d + 1 - last);
  }

  return sc;
}

int main(void) {
  array<ll, 365> ans;

  cin >> D;
  rep(i, 26) cin >> c[i];
  rep(d, 365) rep(i, 26) cin >> s[d][i];

  uniform_int_distribution<ll> dist26(0, 25);
  uniform_real_distribution<double> dist01(0.0, 1.0);
  mt19937 mt;
  rep(d, 365) ans[d] = distance(s[d].begin(), max_element(all(s[d])));

  ll currentScore = score(ans);
  auto bestAns = ans;
  ll bestScore = currentScore;

  ll timeLimit = 1950;

  ll nIters = 0;
  while (true) {
    rep(d, 365) {
      rep(i, 26) {
        ll const timeMicro = gTimer.micro();
        if (timeMicro >= timeLimit * 1000)
          goto NEXT;
        double const prog = timeMicro / (timeLimit * 1000.0);
        if (s[d][i] <= 15000)
          continue;
        ll prev = ans[d];
        ll a0 = scoreDiff(ans, prev);
        ll b0 = scoreDiff(ans, i);
        ans[d] = i;
        ll a1 = scoreDiff(ans, prev);
        ll b1 = scoreDiff(ans, i);
        ll nextScore = currentScore - (a0 + b0) + (a1 + b1);
        double const progg = 1.0 - prog;
        ++nIters;
        if (nextScore > currentScore ||
            exp((nextScore - currentScore) / (1000.0 * progg)) > dist01(mt)) {
          if (nextScore > bestScore) {
            bestScore = nextScore;
            bestAns = ans;
          }
          currentScore = nextScore;
        } else {
          ans[d] = prev;
        }
      }
    }
  }

NEXT:
  ans = bestAns;
  currentScore = bestScore;
  pv(nIters);
  pl;

  /*
      for(double temp = 10.0; temp > 0.01; temp *= 0.80){
          rep(d0, 365) {
              rep2(d1, d0 + 1, 365) {
                  rep(i, 26) {
                      if(gTimer.milli() >= 2 * timeLimit)
                          goto END;
                      if(ans[d0] == ans[d1])
                          continue;
                      ll a0 = scoreDiff(ans, ans[d0]);
                      ll b0 = scoreDiff(ans, ans[d1]);
                      swap(ans[d0], ans[d1]);
                      ll a1 = scoreDiff(ans, ans[d0]);
                      ll b1 = scoreDiff(ans, ans[d1]);
                      ll nextScore = currentScore - (a0 + b0) + (a1 + b1);
                      if (nextScore > currentScore || exp((nextScore -
     currentScore) / temp) > dist01(mt)) { if(nextScore > bestScore){ bestScore
     = nextScore; bestAns = ans; pv(bestScore);
                          }
                          currentScore = nextScore;
                      } else {
                          swap(ans[d0], ans[d1]);
                      }
                  }
              }
          }
      }
      */

END:
  rep(d, 365) cout << bestAns[d] + 1 << endl;

  return 0;
}


Error: TLE

Fixed submission:

#include <algorithm>
#include <array>
#include <bitset>
#include <chrono>
#include <cmath>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

#include <cstring>

using namespace std;

using ll = long long;
using ull = unsigned long long;
ll const MM = 1000000007;
// ll const NN = 1000000007;

#define pv(val) cerr << #val << '=' << (val) << endl
#define pl cerr << '@' << __LINE__ << endl

#define rep(i, n) for (ll i = 0; i < (n); i++)
#define rep2(i, b, e) for (ll i = (b); i < (e); i++)
#define all(a) a.begin(), a.end()
#define rall(a) a.rbegin(), a.rend()

template <class T> ostream &operator<<(ostream &os, vector<T> const &vec);
template <class T, size_t S>
ostream &operator<<(ostream &os, array<T, S> const &arr);
template <class T, class U>
ostream &operator<<(ostream &os, pair<T, U> const &p);
template <class... Args>
ostream &operator<<(ostream &os, tuple<Args...> const &t);

template <class T> ostream &operator<<(ostream &os, vector<T> const &vec) {
  if (vec.empty()) {
    os << "{}";
  } else {
    os << '{';
    for (size_t i = 0; i < vec.size() - 1; i++)
      os << vec[i] << ", ";
    os << vec.back() << '}';
  }
  return os;
}

template <class T, size_t S>
ostream &operator<<(ostream &os, array<T, S> const &arr) {
  if (arr.empty()) {
    os << "{}";
  } else {
    os << '{';
    for (size_t i = 0; i < arr.size() - 1; i++)
      os << arr[i] << ", ";
    os << arr.back() << '}';
  }
  return os;
}

template <class T, class U>
ostream &operator<<(ostream &os, pair<T, U> const &p) {
  os << '(' << p.first << ", " << p.second << ')';
  return os;
}

template <size_t I, class... Args>
typename enable_if<sizeof...(Args) == (I + 1)>::type
print_tuple(ostream &os, tuple<Args...> const &t) {
  os << get<I>(t);
}
template <size_t I, class... Args>
typename enable_if<sizeof...(Args) != (I + 1)>::type
print_tuple(ostream &os, tuple<Args...> const &t) {
  os << get<I>(t) << ", ";
  print_tuple<I + 1, Args...>(os, t);
}

template <class... Args>
ostream &operator<<(ostream &os, tuple<Args...> const &t) {
  os << '(';
  print_tuple<0, Args...>(os, t);
  os << ')';

  return os;
}

struct Timer {
  using Clock = std::chrono::system_clock;
  Clock::time_point startTime;

  Timer() { start(); }
  void start() { startTime = Clock::now(); }

  long long milli() const {
    return std::chrono::duration_cast<std::chrono::milliseconds>(Clock::now() -
                                                                 startTime)
        .count();
  }
  long long micro() const {
    return std::chrono::duration_cast<std::chrono::microseconds>(Clock::now() -
                                                                 startTime)
        .count();
  }
};

ll bound(function<bool(ll)> f, ll ng, ll ok) {
  while (abs(ng - ok) > 1) {
    ll mid = (ng + ok) / 2;
    if (f(mid))
      ok = mid;
    else
      ng = mid;
  }

  return ok;
}

ll order(vector<ll> const &r) {
  vector<ll> a(r.size());
  iota(all(a), 1);

  ll ord = 0;
  while (a != r) {
    next_permutation(all(a));
    ord++;
  }

  return ord;
}

ll div(ll n) {
  ll ans = 0;
  while (n > 0) {
    ans++;
    n /= 2;
  }

  return ans;
}

// value, weight
ll knapsack(vector<pair<ll, ll>> const &a, ll max_w) {
  ll max_n = a.size();
  vector<ll> table(max_w + 1, 0);

  for (int i = 1; i <= max_n; ++i) {
    ll v = a[i].first;
    ll w = a[i].second;
    if (w <= max_w && table[w] < v)
      table[w] = v;
    for (int j = 1; j <= max_w - w; j++) {
      if (table[j] != 0 && table[w + j] < table[j] + v)
        table[w + j] = table[j] + v;
    }
  }

  return *max_element(all(table));
}

ll llpow(ll n, ll m) {
  ll ans = 1;
  rep(i, m) {
    ans *= n;
    ans %= MM;
  }

  return ans;
}

Timer gTimer;

ll D;
array<ll, 26> c;
array<array<ll, 26>, 365> s;
ll score(array<ll, 365> const &ans) {
  ll sc = 0;
  array<ll, 26> last = {};
  rep(d, 365) {
    last[ans[d]] = d + 1;
    rep(i, 26) sc -= c[i] * (d + 1 - last[i]);
    sc += s[d][ans[d]];
  }

  return sc;
}

ll scoreDiff(array<ll, 365> const &ans, ll i) {
  ll sc = 0;
  ll last = 0;
  rep(d, 365) {
    if (ans[d] == i) {
      last = d + 1;
      sc += s[d][i];
    }
    sc -= c[i] * (d + 1 - last);
  }

  return sc;
}

int main(void) {
  array<ll, 365> ans;

  cin >> D;
  rep(i, 26) cin >> c[i];
  rep(d, 365) rep(i, 26) cin >> s[d][i];

  uniform_int_distribution<ll> dist26(0, 25);
  uniform_real_distribution<double> dist01(0.0, 1.0);
  mt19937 mt;
  rep(d, 365) ans[d] = distance(s[d].begin(), max_element(all(s[d])));

  ll currentScore = score(ans);
  auto bestAns = ans;
  ll bestScore = currentScore;

  ll timeLimit = 10 * 1950;

  ll nIters = 0;
  while (true) {
    rep(d, 365) {
      rep(i, 26) {
        ll const timeMicro = gTimer.micro();
        if (timeMicro >= timeLimit * 1000)
          goto NEXT;
        double const prog = timeMicro / (timeLimit * 1000.0);
        if (s[d][i] <= 15000)
          continue;
        ll prev = ans[d];
        ll a0 = scoreDiff(ans, prev);
        ll b0 = scoreDiff(ans, i);
        ans[d] = i;
        ll a1 = scoreDiff(ans, prev);
        ll b1 = scoreDiff(ans, i);
        ll nextScore = currentScore - (a0 + b0) + (a1 + b1);
        double const progg = 1.0 - prog;
        ++nIters;
        if (nextScore > currentScore ||
            exp((nextScore - currentScore) / (1000.0 * progg)) > dist01(mt)) {
          if (nextScore > bestScore) {
            bestScore = nextScore;
            bestAns = ans;
          }
          currentScore = nextScore;
        } else {
          ans[d] = prev;
        }
      }
    }
  }

NEXT:
  ans = bestAns;
  currentScore = bestScore;
  pv(nIters);
  pl;

  /*
      for(double temp = 10.0; temp > 0.01; temp *= 0.80){
          rep(d0, 365) {
              rep2(d1, d0 + 1, 365) {
                  rep(i, 26) {
                      if(gTimer.milli() >= 2 * timeLimit)
                          goto END;
                      if(ans[d0] == ans[d1])
                          continue;
                      ll a0 = scoreDiff(ans, ans[d0]);
                      ll b0 = scoreDiff(ans, ans[d1]);
                      swap(ans[d0], ans[d1]);
                      ll a1 = scoreDiff(ans, ans[d0]);
                      ll b1 = scoreDiff(ans, ans[d1]);
                      ll nextScore = currentScore - (a0 + b0) + (a1 + b1);
                      if (nextScore > currentScore || exp((nextScore -
     currentScore) / temp) > dist01(mt)) { if(nextScore > bestScore){ bestScore
     = nextScore; bestAns = ans; pv(bestScore);
                          }
                          currentScore = nextScore;
                      } else {
                          swap(ans[d0], ans[d1]);
                      }
                  }
              }
          }
      }
      */

END:
  rep(d, 365) cout << bestAns[d] + 1 << endl;

  return 0;
}