Submission #1887865


Source Code Expand

#include <sys/time.h>
#include <algorithm>
#include <climits>
#include <cmath>
#include <cstring>
#include <iostream>
#include <vector>
using namespace std;

class Timer {
 public:
  void restart();
  double getElapsed();

  Timer();

 private:
  static double rdtsc_per_sec_inv;

  double getTimeOfDay();
  unsigned long long int getCycle();

  double start_time;
  unsigned long long int start_clock;
};
double Timer::rdtsc_per_sec_inv = -1;

inline double Timer::getElapsed() {
  if (rdtsc_per_sec_inv != -1)
    return (double)(getCycle() - start_clock) * rdtsc_per_sec_inv;

  const double RDTSC_MEASUREMENT_INTERVAL = 0.1;
  double res = getTimeOfDay() - start_time;
  if (res <= RDTSC_MEASUREMENT_INTERVAL) return res;

  rdtsc_per_sec_inv = 1.0 / (getCycle() - start_clock);
  rdtsc_per_sec_inv *= getTimeOfDay() - start_time;
  return getElapsed();
}

inline void Timer::restart() {
  start_time = getTimeOfDay();
  start_clock = getCycle();
}

Timer::Timer() { restart(); }

inline double Timer::getTimeOfDay() {
  timeval tv;
  gettimeofday(&tv, 0);
  return tv.tv_sec + tv.tv_usec * 0.000001;
}

inline unsigned long long int Timer::getCycle() {
  unsigned int low, high;
  __asm__ volatile("rdtsc" : "=a"(low), "=d"(high));
  return ((unsigned long long int)low) | ((unsigned long long int)high << 32);
}

Timer timer;

inline unsigned get_random() {
  static unsigned y = 2463534242;
  return y ^= (y ^= (y ^= y << 13) >> 17) << 5;
}

constexpr double TIME_LIMIT = 1.9;
constexpr int ROW = 1 << 5;
constexpr int MAX_V = 1 << 9;
constexpr int MAX_KV = ROW * ROW;
constexpr int WALL = MAX_V - 1;

int V, E, KV, KE, KR;
uint8_t W[MAX_V][MAX_V];
uint8_t P[MAX_KV];
uint16_t X[MAX_KV];

int bestScore = 0;
uint16_t best[MAX_KV];

struct Node {
  int16_t pos;
  int16_t vertex;
  int16_t score;
  int value;
};
Node state[MAX_KV][MAX_V];

int value(int p) {
  uint8_t* w = W[X[p]];
  return w[X[p - ROW - 1]] + w[X[p - ROW]] + w[X[p - ROW + 1]] + w[X[p - 1]] +
         w[X[p + 1]] + w[X[p + ROW - 1]] + w[X[p + ROW]] + w[X[p + ROW + 1]];
}

void diff(int p, int n) {
  uint8_t* wp = W[X[p]];
  uint8_t* wn = W[X[n]];
  auto set = [&](int t) {
    P[t] -= wp[X[t]];
    P[t] += wn[X[t]];
  };
  set(n - ROW - 1);
  set(n - ROW);
  set(n - ROW + 1);
  set(n - 1);
  set(n + 1);
  set(n + ROW - 1);
  set(n + ROW);
  set(n + ROW + 1);
}

int main() {
  {  // input
    memset(W, 0, sizeof(W));
    scanf("%d%d\n", &V, &E);
    int u, v, t;
    for (int i = 0; i < E; ++i) {
      scanf("%d%d%d\n", &u, &v, &t);
      --u;
      --v;
      W[u][v] = t;
      W[v][u] = t;
    }
    scanf("%d%d\n", &KV, &KE);
    KR = sqrt(KV);
  }
  int R = min(KR, ROW - 2);
  {  // Hill Climbing
    int wsum[MAX_KV];
    memset(wsum, 0, sizeof(wsum));
    for (int i = 0; i < V; ++i) {
      for (int j = 0; j < V; ++j) {
        wsum[i] += W[i][j];
      }
    }
    Node* bestVertex[MAX_KV];
    bool ok[MAX_KV];
    memset(ok, false, sizeof(ok));
    vector<int16_t> vertexes(MAX_V);
    vertexes.clear();
    vector<int16_t> positions(MAX_KV);
    for (int time = 0; time < 100; ++time) {
      positions.clear();
      for (int i = 0; i < MAX_KV; ++i) X[i] = WALL;
      for (int i = 0; i < V; ++i) vertexes.emplace_back(i);
      for (int i = 1; i <= R; ++i) {
        for (int j = 1; j <= R; ++j) {
          int p = i * ROW + j;
          ok[p] = true;
          X[p] = V;
          bestVertex[p] = &state[p][vertexes[0]];
          for (int k = 0; k < V; ++k) {
            state[p][k].pos = p;
            state[p][k].vertex = k;
            state[p][k].score = 0;
            state[p][k].value = INT_MIN;
          }
        }
      }
      int score = 0;
      auto update = [&](int n, int p) {
        if (X[p] != V) return;
        int value = -1;
        auto add = [&](Node& n, int v, int u) {
          if (u < V) {
            int t = W[v][u];
            if (t) {
              n.score += t;
              n.value += t << 14;
            } else {
              n.value -= 1 << 10;
            }
          }
        };
        for (int v : vertexes) {
          if (ok[p]) {
            state[p][v].score = 0;
            state[p][v].value = wsum[v];
            add(state[p][v], v, X[p - ROW - 1]);
            add(state[p][v], v, X[p - ROW]);
            add(state[p][v], v, X[p - ROW + 1]);
            add(state[p][v], v, X[p - 1]);
            add(state[p][v], v, X[p + 1]);
            add(state[p][v], v, X[p + ROW - 1]);
            add(state[p][v], v, X[p + ROW]);
            add(state[p][v], v, X[p + ROW + 1]);
          } else {
            add(state[p][v], v, X[n]);
          }
          int t = state[p][v].value + (get_random() & ((1 << 10) - 1));
          if (value < t) {
            value = t;
            bestVertex[p] = &state[p][v];
          }
        }
        if (ok[p]) {
          ok[p] = false;
          positions.emplace_back(p);
        }
      };
      update(-1, (R / 2 + 1) * ROW + (R / 2 + 1));
      for (int i = 0; i < V; ++i) {
        Node* n = bestVertex[positions[0]];
        int value = INT_MIN;
        for (int p : positions) {
          if (bestVertex[p]->value < 0) {
            int value = INT_MIN;
            for (int v : vertexes) {
              if (value < state[p][v].value) {
                value = state[p][v].value;
                bestVertex[p] = &state[p][v];
              }
            }
          }
          int t = bestVertex[p]->value + (get_random() & ((1 << 10) - 1));
          if (value < t) {
            value = t;
            n = bestVertex[p];
          }
        }
        X[n->pos] = n->vertex;
        vertexes.erase(find(vertexes.begin(), vertexes.end(), n->vertex));
        positions.erase(find(positions.begin(), positions.end(), n->pos));
        score += n->score;
        for (int p : positions) state[p][n->vertex].value = -1000000;
        update(n->pos, n->pos - ROW - 1);
        update(n->pos, n->pos - ROW);
        update(n->pos, n->pos - ROW + 1);
        update(n->pos, n->pos - 1);
        update(n->pos, n->pos + 1);
        update(n->pos, n->pos + ROW - 1);
        update(n->pos, n->pos + ROW);
        update(n->pos, n->pos + ROW + 1);
      }
      if (bestScore < score) {
        bestScore = score;
        memcpy(best, X, sizeof(X));
      }
    }
  }
  {  // Simulated Annealing
    constexpr int LOG_SIZE = 1 << 10;
    double log_d[LOG_SIZE];
    uint8_t log_[LOG_SIZE];
    memcpy(X, best, sizeof(X));
    memset(P, 0, sizeof(P));
    uint16_t POS[MAX_KV];
    for (int i = 1; i <= R; ++i) {
      for (int j = 1; j <= R; ++j) {
        int p = i * ROW + j;
        P[p] = value(p);
        POS[X[p]] = p;
      }
    }
    {
      double x = min(4.5, 1.0 + 0.5 * E / V);
      for (int i = 0; i < LOG_SIZE; ++i) {
        log_d[i] = -1 * x * log((i + 0.5) / LOG_SIZE) / TIME_LIMIT;
      }
    }
    constexpr static int8_t DIR[] = {-ROW - 1, -ROW,     -ROW + 1, -1,
                                     +1,       +ROW - 1, +ROW,     +ROW + 1};
    uint16_t SV[MAX_V][MAX_V];
    for (int i = 0; i < V; ++i) {
      for (int j = 0; j < V; ++j) {
        SV[i][j] = j;
      }
      sort(SV[i], SV[i] + V,
           [i](uint16_t& a, uint16_t& b) { return W[i][a] > W[i][b]; });
    }
    int cs = bestScore;
    while (true) {
      double time = TIME_LIMIT - timer.getElapsed();
      if (time < 0) break;
      for (int i = 0; i < LOG_SIZE; ++i)
        log_[i] = min(20.0, round(log_d[i] * time));
      for (int t = 0; t < 0x10000; ++t) {
        unsigned m = get_random();
        int x1 = (m >> 13) % V;
        int p1 = POS[x1];
        int x2 = SV[x1][get_random() % (V >> 4)];
        int p2 = POS[x2] + DIR[(m >> 10) & ((1 << 3) - 1)];
        if (X[p2] == WALL) continue;
        int pv = P[p1] + P[p2];
        swap(X[p1], X[p2]);
        int v1 = value(p1), v2 = value(p2);
        int d = pv - v1 - v2;
        if (d > log_[m & (LOG_SIZE - 1)]) {
          swap(X[p1], X[p2]);
        } else {
          diff(p2, p1);
          diff(p1, p2);
          P[p1] = v1;
          P[p2] = v2;
          POS[X[p1]] = p1;
          POS[X[p2]] = p2;
          cs -= d;
          if (bestScore < cs) {
            bestScore = cs;
            memcpy(best, X, sizeof(X));
          }
        }
      }
    }
  }
  {  // output
    for (int i = 0; i < MAX_KV; ++i) {
      if (best[i] < V)
        printf("%d %d\n", best[i] + 1, (i / ROW - 1) * KR + i % ROW);
    }
  }
}

Submission Info

Submission Time
Task A - Problem 1
User hoshi524
Language C++14 (Clang 3.8.0)
Score 161342
Code Size 8702 Byte
Status RE
Exec Time 1904 ms
Memory 6784 KB

Compile Error

./Main.cpp:64:18: warning: unsequenced modification and access to 'y' [-Wunsequenced]
  return y ^= (y ^= (y ^= y << 13) >> 17) << 5;
           ~~    ^
1 warning generated.

Judge Result

Set Name sample_00 sample_01 random_00 random_01 random_02 random_03 random_04 random_05 random_06 random_07 random_08 full_00 full_01 full_02 full_03 full_04 full_05 full_06 full_07 full_08 sparse_00 sparse_01 sparse_02 sparse_03 sparse_04 sparse_05 sparse_06 sparse_07 random_max full_max
Score / Max Score 0 / 1000000 0 / 1000000 1684 / 1000000 9559 / 1000000 14615 / 1000000 6651 / 1000000 1256 / 1000000 10753 / 1000000 10017 / 1000000 6180 / 1000000 7021 / 1000000 7483 / 1000000 4753 / 1000000 0 / 1000000 2156 / 1000000 4596 / 1000000 8882 / 1000000 1793 / 1000000 3914 / 1000000 4236 / 1000000 5149 / 1000000 2094 / 1000000 4682 / 1000000 3934 / 1000000 6632 / 1000000 2505 / 1000000 3930 / 1000000 1870 / 1000000 15566 / 1000000 9431 / 1000000
Status
RE × 1
RE × 1
AC × 1
AC × 1
AC × 1
AC × 1
AC × 1
AC × 1
AC × 1
AC × 1
AC × 1
AC × 1
AC × 1
RE × 1
AC × 1
AC × 1
AC × 1
AC × 1
AC × 1
AC × 1
AC × 1
AC × 1
AC × 1
AC × 1
AC × 1
AC × 1
AC × 1
AC × 1
AC × 1
AC × 1
Set Name Test Cases
sample_00 00_sample_00
sample_01 00_sample_01
random_00 10_random_00
random_01 10_random_01
random_02 10_random_02
random_03 10_random_03
random_04 10_random_04
random_05 10_random_05
random_06 10_random_06
random_07 10_random_07
random_08 10_random_08
full_00 20_full_00
full_01 20_full_01
full_02 20_full_02
full_03 20_full_03
full_04 20_full_04
full_05 20_full_05
full_06 20_full_06
full_07 20_full_07
full_08 20_full_08
sparse_00 30_sparse_00
sparse_01 30_sparse_01
sparse_02 30_sparse_02
sparse_03 30_sparse_03
sparse_04 30_sparse_04
sparse_05 30_sparse_05
sparse_06 30_sparse_06
sparse_07 30_sparse_07
random_max 60_random_max_00
full_max 70_full_max_00
Case Name Status Exec Time Memory
00_sample_00 RE 97 ms 512 KB
00_sample_01 RE 97 ms 768 KB
10_random_00 AC 1902 ms 3200 KB
10_random_01 AC 1903 ms 3712 KB
10_random_02 AC 1902 ms 6656 KB
10_random_03 AC 1902 ms 6272 KB
10_random_04 AC 1902 ms 2944 KB
10_random_05 AC 1903 ms 6528 KB
10_random_06 AC 1904 ms 6272 KB
10_random_07 AC 1903 ms 6272 KB
10_random_08 AC 1903 ms 5888 KB
20_full_00 AC 1902 ms 6016 KB
20_full_01 AC 1902 ms 6144 KB
20_full_02 RE 99 ms 640 KB
20_full_03 AC 1903 ms 5632 KB
20_full_04 AC 1903 ms 3328 KB
20_full_05 AC 1901 ms 3712 KB
20_full_06 AC 1902 ms 5760 KB
20_full_07 AC 1901 ms 3584 KB
20_full_08 AC 1902 ms 3200 KB
30_sparse_00 AC 1903 ms 6656 KB
30_sparse_01 AC 1904 ms 3584 KB
30_sparse_02 AC 1903 ms 6656 KB
30_sparse_03 AC 1904 ms 6656 KB
30_sparse_04 AC 1902 ms 6272 KB
30_sparse_05 AC 1902 ms 6528 KB
30_sparse_06 AC 1904 ms 6656 KB
30_sparse_07 AC 1902 ms 6016 KB
60_random_max_00 AC 1903 ms 6784 KB
70_full_max_00 AC 1902 ms 6400 KB