結果

問題 No.5002 stick xor
ユーザー Hoi_koroHoi_koro
提出日時 2018-05-29 23:20:14
言語 C++14
(gcc 13.2.0 + boost 1.83.0)
結果
AC  
実行時間 977 ms / 1,000 ms
コード長 10,139 bytes
コンパイル時間 35,114 ms
実行使用メモリ 1,700 KB
スコア 51,325
最終ジャッジ日時 2018-05-29 23:20:51
ジャッジサーバーID
(参考情報)
judge7 /
純コード判定しない問題か言語
このコードへのチャレンジ(β)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 975 ms
1,688 KB
testcase_01 AC 975 ms
1,648 KB
testcase_02 AC 976 ms
1,648 KB
testcase_03 AC 974 ms
1,692 KB
testcase_04 AC 976 ms
1,652 KB
testcase_05 AC 975 ms
1,652 KB
testcase_06 AC 975 ms
1,692 KB
testcase_07 AC 975 ms
1,692 KB
testcase_08 AC 976 ms
1,648 KB
testcase_09 AC 977 ms
1,648 KB
testcase_10 AC 976 ms
1,688 KB
testcase_11 AC 975 ms
1,652 KB
testcase_12 AC 975 ms
1,652 KB
testcase_13 AC 977 ms
1,696 KB
testcase_14 AC 974 ms
1,652 KB
testcase_15 AC 976 ms
1,692 KB
testcase_16 AC 975 ms
1,652 KB
testcase_17 AC 974 ms
1,700 KB
testcase_18 AC 974 ms
1,696 KB
testcase_19 AC 976 ms
1,652 KB
testcase_20 AC 976 ms
1,696 KB
testcase_21 AC 977 ms
1,652 KB
testcase_22 AC 974 ms
1,648 KB
testcase_23 AC 976 ms
1,652 KB
testcase_24 AC 975 ms
1,648 KB
testcase_25 AC 976 ms
1,688 KB
testcase_26 AC 974 ms
1,692 KB
testcase_27 AC 976 ms
1,652 KB
testcase_28 AC 976 ms
1,656 KB
testcase_29 AC 976 ms
1,648 KB
testcase_30 AC 976 ms
1,648 KB
testcase_31 AC 974 ms
1,688 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <bits/stdc++.h>

#if MYDEBUG
#include "lib/cp_debug.hpp"
#else
#define DBG(...) ;
#endif

using LL = long long;
constexpr LL LINF = 334ll << 53;
constexpr int INF = 15 << 26;
constexpr LL MOD = 1E9 + 7;

namespace Problem {
using namespace std;

struct Rec {
  int dir,   // direction(0,horizontal, 1:vertical),
      y, x;  // coordinate left-upper corner
};
uint32_t x = 123456789, y = 362436069, z = 521288629, w = 88675123;
uint32_t xor128() {
  uint32_t t = x ^ (x << 11);
  x = y;
  y = z;
  z = w;
  return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));
}
class Solver {
 public:
  int n, k;
  vector<int> len;
  vector<LL> grid;
  vector<Rec> rec, ans;
  random_device rnd;
  mt19937 mt;
  chrono::system_clock::time_point start = chrono::system_clock::now();
  Solver(LL n, LL k) : n(n), k(k), len(k), grid(n, 0), rec(k), mt(rnd()){};

  void calc_SA() {
    double temp1 = 0.98, temp2 = 0.99, temp3 = 1.0;
    int q, d, x, y;
    int score = -evaluate(grid, rec), max_score;
    double diff;
    DBG(score)
    for (int i = 0; i < k; ++i) {
      d = xor128() % 2;
      y = xor128() % n;
      x = xor128() % (n - len[i] + 1);
      if (d == 1) swap(x, y);
      add_rectangle(grid, rec, i, d, y, x);
    }
    score += evaluate(grid, rec);
    max_score = score;
    ans = rec;
    DBG(score)
    int loop = 0;

    while (!time_limit()) {
      // cerr << temp3 << ' ' << score << endl;
      for (int _ = 0; _ < 10000; ++_) {
        // first
        q = xor128() % k;
        x = xor128() % 2 * 2 - 1;
        if (rec[q].dir == 0) {
          if (x == -1 and rec[q].x > 0) {
            diff = (((grid[rec[q].y] >> (rec[q].x - 1)) & 1) +
                    ((grid[rec[q].y] >> (rec[q].x + len[q] - 1)) & 1)) *
                       2 -
                   2;
            if ((double)xor128() / (double)(1ll << 32) < exp(diff / temp1)) {
              grid[rec[q].y] ^= (1ll << (rec[q].x - 1));
              grid[rec[q].y] ^= (1ll << (rec[q].x + len[q] - 1));
              rec[q].x--;
              score += diff;
              if (score > max_score) {
                max_score = score;
                ans = rec;
              }
            }
          } else if (x == 1 and rec[q].x + len[q] < n) {
            diff = (((grid[rec[q].y] >> (rec[q].x)) & 1) +
                    ((grid[rec[q].y] >> (rec[q].x + len[q])) & 1)) *
                       2 -
                   2;
            if ((double)xor128() / (double)(1ll << 32) < exp(diff / temp1)) {
              grid[rec[q].y] ^= (1ll << (rec[q].x));
              grid[rec[q].y] ^= (1ll << (rec[q].x + len[q]));
              rec[q].x++;
              score += diff;
              if (score > max_score) {
                max_score = score;
                ans = rec;
              }
            }
          }
        } else {
          if (x == -1 and rec[q].y > 0) {
            diff = (((grid[rec[q].y - 1] >> (rec[q].x)) & 1) +
                    ((grid[rec[q].y + len[q] - 1] >> (rec[q].x)) & 1)) *
                       2 -
                   2;
            if ((double)xor128() / (double)(1ll << 32) < exp(diff / temp1)) {
              grid[rec[q].y - 1] ^= (1ll << rec[q].x);
              grid[rec[q].y + len[q] - 1] ^= (1ll << rec[q].x);
              rec[q].y--;
              score += diff;
              if (score > max_score) {
                max_score = score;
                ans = rec;
              }
            }
          } else if (x == 1 and rec[q].y + len[q] < n) {
            diff = (((grid[rec[q].y] >> (rec[q].x)) & 1) +
                    ((grid[rec[q].y + len[q]] >> (rec[q].x)) & 1)) *
                       2 -
                   2;

            if ((double)xor128() / (double)(1ll << 32) < exp(diff / temp1)) {
              grid[rec[q].y] ^= (1ll << rec[q].x);
              grid[rec[q].y + len[q]] ^= (1ll << rec[q].x);
              rec[q].y++;
              score += diff;
              if (score > max_score) {
                max_score = score;
                ans = rec;
              }
            }
          }
        }

        // second : swap the length of two rectangles
        q = xor128() % k;
        do {
          d = xor128() % k;
        } while (rec[d].dir != rec[q].dir or
                 (rec[d].dir == 0 and rec[q].y == rec[d].y) or
                 (rec[d].dir == 1 and rec[q].x == rec[d].x));
        if (len[q] < len[d]) swap(q, d);
        diff = -2 * (len[q] - len[d]);
        if (len[q] > len[d]) {
          if (rec[d].dir == 0 and rec[d].x + len[q] <= n) {
            LL mask = (1ll << len[q]) - (1ll << len[d]);
            diff +=
                __builtin_popcountll((mask << rec[q].x) & grid[rec[q].y]) * 2;
            diff +=
                __builtin_popcountll((mask << rec[d].x) & grid[rec[d].y]) * 2;
            if ((double)xor128() / (double)(1ll << 32) < exp(diff / temp2)) {
              score += diff;
              grid[rec[q].y] ^= (mask << rec[q].x);
              grid[rec[d].y] ^= (mask << rec[d].x);
              swap(rec[q], rec[d]);
              if (score > max_score) {
                max_score = score;
                ans = rec;
              }
            }
          } else if (rec[d].dir == 1 and rec[d].y + len[q] <= n) {
            for (int l = len[d]; l < len[q]; ++l) {
              diff += ((grid[rec[q].y + l] >> (rec[q].x)) & 1) << 1;
              diff += ((grid[rec[d].y + l] >> (rec[d].x)) & 1) << 1;
            }
            if ((double)xor128() / (double)(1ll << 32) < exp(diff / temp2)) {
              score += diff;
              for (int l = len[d]; l < len[q]; ++l) {
                grid[rec[q].y + l] ^= (1ll << rec[q].x);
                grid[rec[d].y + l] ^= (1ll << rec[d].x);
              }
              swap(rec[q], rec[d]);
              if (score > max_score) {
                max_score = score;
                ans = rec;
              }
            }
          }
        }

        // third
        loop++;
        q = xor128() % k;
        d = xor128() % 2;
        y = xor128() % n;
        x = xor128() % (n - len[q] + 1);
        if (d == 1) swap(x, y);
        auto tmp = rec[q];
        diff = remove_rectangle(grid, rec, q) +
               add_rectangle(grid, rec, q, d, y, x);

        if ((double)xor128() / (double)(1ll << 32) < exp(diff / temp3)) {
          // DBG(score, diff)
          score += diff;
          if (score > max_score) {
            max_score = score;
            ans = rec;
          }
        } else {
          remove_rectangle(grid, rec, q);
          add_rectangle(grid, rec, q, tmp.dir, tmp.y, tmp.x);
        }
      }

      DBG(temp1, score)
      temp3 = update_temperature();
      temp2 = 1.0 / (1.0 / temp3 + 0.004);
      temp1 = 1.0 / (1.0 / temp2 + 0.004);
      // temp2 = temp3 - pow(temp3, 2.01);
      // temp1 = temp2 - pow(temp2, 2.02);
    }
    cerr << max_score << endl;
    cerr << loop << endl;
  }
  int evaluate(vector<LL>& gr, vector<Rec>& r) {
    int ret = n * n;
    for (int i = 0; i < n; ++i) {
      ret -= __builtin_popcountll(gr[i]);
    }
    return ret;
  }
  int remove_rectangle(vector<LL>& gr, vector<Rec>& r, int i) {
    int ret = 0;
    int yy = r[i].y;
    int xx = r[i].x;
    if (r[i].dir == 1) {
      for (int j = 0; j < len[i]; ++j) {
        ret += ((gr[yy] >> xx) & 1);
        gr[yy] ^= (1ll << xx);
        yy++;
      }
    } else {
      LL mask = (1ll << (xx + len[i])) - (1ll << xx);
      ret += __builtin_popcountll(mask & gr[yy]);
      gr[yy] ^= mask;
    }
    return 2 * ret - len[i];
  }
  int add_rectangle(vector<LL>& gr, vector<Rec>& r, int i, int dir, int y,
                    int x) {
    r[i] = {dir, y, x};
    int ret = 0;
    if (dir == 1) {
      for (int j = 0; j < len[i]; ++j) {
        ret += ((gr[y] >> x) & 1);
        gr[y] ^= (1ll << x);
        y++;
      }
    } else {
      LL mask = (1ll << (x + len[i])) - (1ll << x);
      ret += __builtin_popcountll(mask & gr[y]);
      gr[y] ^= mask;
    }
    return 2 * ret - len[i];
  }
  void input() {
    for (int i = 0; i < k; ++i) {
      cin >> len[i];
    }
    int tmp = 0;
    for (int i = 0; i < n; ++i) {
      for (int j = 0; j < n; ++j) {
        char tmp;
        cin >> tmp;
        grid[i] += ((LL)(tmp - '0') << j);
      }
      tmp += __builtin_popcountll(grid[i]);
    }
    DBG(tmp)
  }
  void output() {
    for (int i = 0; i < k; ++i) {
      if (ans[i].dir == 0) {
        cout << ans[i].y + 1 << ' ' << ans[i].x + 1 << ' ' << ans[i].y + 1
             << ' ' << ans[i].x + len[i] << "\n";
      } else {
        cout << ans[i].y + 1 << ' ' << ans[i].x + 1 << ' ' << ans[i].y + len[i]
             << ' ' << ans[i].x + 1 << "\n";
      }
    }
  }
  void solve() {
    input();

    // randomize initial state
    uniform_int_distribution<int> seed(0, 100);
    int loop = seed(mt);
    for (int i = 0; i < loop; ++i) {
      xor128();
    }

    calc_SA();
    output();
  }
  bool time_limit(double thres = 0.97 * 1) {
    double t = chrono::duration_cast<chrono::milliseconds>(
                   chrono::system_clock::now() - start)
                   .count() /
               1000.0;
#if MYDEBUG
    thres *= 2.4;
#else
    ;
#endif
    return t > thres;
  }
  double update_temperature() {
    double t_left = (1000 - chrono::duration_cast<chrono::milliseconds>(
                                chrono::system_clock::now() - start)
                                .count());
#if MYDEBUG
    t_left = (2400 - chrono::duration_cast<chrono::milliseconds>(
                         chrono::system_clock::now() - start)
                         .count()) /
             2.4;
#else
    ;
#endif
    t_left /= 1000;
    // return 0.8 * pow(t_left, 0.8) * exp((t_left - 1) * 1);
    return 0.8 * exp((t_left - 1) * 2.4) * pow(t_left, 1) *
               ((t_left * (1 - t_left) * (1 - t_left) * 4 + 1)) +
           t_left * (1 - t_left) * (1 - t_left) * (1 - t_left) * 1.5;
    // return t_left/2+0.02;
  }
};  // namespace Problem
}  // namespace Problem

int main() {
  std::cin.tie(0);
  std::ios_base::sync_with_stdio(false);
  long long n = 0, k;
  std::cin >> n >> k;
  Problem::Solver sol(n, k);
  sol.solve();
  return 0;
}
0