結果

問題 No.5002 stick xor
ユーザー Hoi_koroHoi_koro
提出日時 2018-05-29 00:53:19
言語 C++14
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 978 ms / 1,000 ms
コード長 12,174 bytes
コンパイル時間 35,434 ms
実行使用メモリ 1,760 KB
スコア 51,089
最終ジャッジ日時 2018-05-29 00:53:56
ジャッジサーバーID
(参考情報)
judge6 /
純コード判定しない問題か言語
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 976 ms
1,752 KB
testcase_01 AC 974 ms
1,756 KB
testcase_02 AC 974 ms
1,748 KB
testcase_03 AC 975 ms
1,756 KB
testcase_04 AC 973 ms
1,756 KB
testcase_05 AC 976 ms
1,712 KB
testcase_06 AC 974 ms
1,756 KB
testcase_07 AC 975 ms
1,756 KB
testcase_08 AC 975 ms
1,748 KB
testcase_09 AC 976 ms
1,712 KB
testcase_10 AC 975 ms
1,748 KB
testcase_11 AC 975 ms
1,752 KB
testcase_12 AC 974 ms
1,760 KB
testcase_13 AC 977 ms
1,712 KB
testcase_14 AC 974 ms
1,760 KB
testcase_15 AC 974 ms
1,756 KB
testcase_16 AC 974 ms
1,748 KB
testcase_17 AC 975 ms
1,752 KB
testcase_18 AC 975 ms
1,752 KB
testcase_19 AC 975 ms
1,708 KB
testcase_20 AC 978 ms
1,708 KB
testcase_21 AC 975 ms
1,756 KB
testcase_22 AC 975 ms
1,760 KB
testcase_23 AC 976 ms
1,756 KB
testcase_24 AC 975 ms
1,756 KB
testcase_25 AC 976 ms
1,752 KB
testcase_26 AC 974 ms
1,756 KB
testcase_27 AC 974 ms
1,756 KB
testcase_28 AC 975 ms
1,756 KB
testcase_29 AC 976 ms
1,756 KB
testcase_30 AC 975 ms
1,748 KB
testcase_31 AC 974 ms
1,752 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;
  const int ub = 25;
  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 temperature = 10.0;
    int q, d, x, y;
    int score = -evaluate(grid, rec), max_score = score;
    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()) {
      for (int _ = 0; _ < 10000; ++_) {
        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];
        double diff = remove_rectangle(grid, rec, q) +
                      add_rectangle(grid, rec, q, d, y, x);
        remove_rectangle(grid, rec, q);
        add_rectangle(grid, rec, q, tmp.dir, tmp.y, tmp.x);
        if ((double)xor128() / (double)(1ll << 32) < exp(diff / temperature)) {
          remove_rectangle(grid, rec, q);
          add_rectangle(grid, rec, q, d, y, x);
          // DBG(score, diff)
          score += diff;
          if (score > max_score) {
            max_score = score;
            ans = rec;
          }
        }
      }
      DBG(temperature, score)
      temperature = update_temperature();
    }
    cerr << score << ' ' << max_score << ' ' << loop << endl;
  }
  void calc_RESA() {
    double temp1 = 0.98, temp2 = 0.99, temp3 = 1.0;
    int q, d, x, y;
    int score1 = -evaluate(grid, rec), max_score, &score2 = score1,
        &score3 = score1;
    double diff;
    DBG(score1)
    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);
    }
    vector<Rec> &rec1 = rec, &rec2 = rec, &rec3 = rec;
    vector<LL> &gr1 = grid, &gr2 = grid, &gr3 = grid;
    score1 += evaluate(grid, rec);
    max_score = score2 = score3 = score1;
    ans = rec;
    DBG(score1)
    int loop = 0;

    while (!time_limit()) {
      // cerr << temp3 << ' ' << score1 << ' ' << score2 << ' ' << score3 <<
      // endl;
      DBG(score1, score2, score3)

      for (int _ = 0; _ < 10000; ++_) {
        // first
        q = xor128() % k;
        x = xor128() % 2 * 2 - 1;
        if (rec1[q].dir == 0) {
          if (x == -1 and rec1[q].x > 0) {
            diff = (((gr1[rec1[q].y] >> (rec1[q].x - 1)) & 1) +
                    ((gr1[rec1[q].y] >> (rec1[q].x + len[q] - 1)) & 1)) *
                       2 -
                   2;
            if ((double)xor128() / (double)(1ll << 32) < exp(diff / temp1)) {
              gr1[rec1[q].y] ^= (1ll << (rec1[q].x - 1));
              gr1[rec1[q].y] ^= (1ll << (rec1[q].x + len[q] - 1));
              rec1[q].x--;
              score1 += diff;
              if (score1 > max_score) {
                max_score = score1;
                ans = rec1;
              }
            }
          } else if (x == 1 and rec1[q].x + len[q] < n) {
            diff = (((gr1[rec1[q].y] >> (rec1[q].x)) & 1) +
                    ((gr1[rec1[q].y] >> (rec1[q].x + len[q])) & 1)) *
                       2 -
                   2;
            if ((double)xor128() / (double)(1ll << 32) < exp(diff / temp1)) {
              gr1[rec1[q].y] ^= (1ll << (rec1[q].x));
              gr1[rec1[q].y] ^= (1ll << (rec1[q].x + len[q]));
              rec1[q].x++;
              score1 += diff;
              if (score1 > max_score) {
                max_score = score1;
                ans = rec1;
              }
            }
          }
        } else {
          if (x == -1 and rec1[q].y > 0) {
            diff = (((gr1[rec1[q].y - 1] >> (rec1[q].x)) & 1) +
                    ((gr1[rec1[q].y + len[q] - 1] >> (rec1[q].x)) & 1)) *
                       2 -
                   2;
            if ((double)xor128() / (double)(1ll << 32) < exp(diff / temp1)) {
              gr1[rec1[q].y - 1] ^= (1ll << rec1[q].x);
              gr1[rec1[q].y + len[q] - 1] ^= (1ll << rec1[q].x);
              rec1[q].y--;
              score1 += diff;
              if (score1 > max_score) {
                max_score = score1;
                ans = rec1;
              }
            }
          } else if (x == 1 and rec1[q].y + len[q] < n) {
            diff = (((gr1[rec1[q].y] >> (rec1[q].x)) & 1) +
                    ((gr1[rec1[q].y + len[q]] >> (rec1[q].x)) & 1)) *
                       2 -
                   2;

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

        // 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 = rec3[q];
        diff = remove_rectangle(gr3, rec3, q) +
               add_rectangle(gr3, rec3, q, d, y, x);

        if ((double)xor128() / (double)(1ll << 32) < exp(diff / temp3)) {
          // DBG(score, diff)
          score3 += diff;
          if (score3 > max_score) {
            max_score = score3;
            ans = rec3;
          }
        } else {
          remove_rectangle(gr3, rec3, q);
          add_rectangle(gr3, rec3, q, tmp.dir, tmp.y, tmp.x);
        }
        // swap
        if ((double)xor128() / (double)(1ll << 32) <
            exp((score2 - score1) * (temp2 - temp1) / (temp1 * temp2))) {
          swap(rec1, rec2);
          swap(gr1, gr2);
          swap(score1, score2);
        }
        if ((double)xor128() / (double)(1ll << 32) <
            exp((score3 - score2) * (temp3 - temp2) / (temp2 * temp3))) {
          swap(rec2, rec3);
          swap(gr2, gr3);
          swap(score2, score3);
        }
      }

      DBG(temp1, score1)
      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_RESA();
    output();
  }
  bool time_limit(double thres = 0.97) {
    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 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