Skip to content

ビットボード

概要

  • 2次元グリッドの各マスを1bitで表現
  • 省メモリや、bit演算で処理することによる高速化が期待できる

コード

template <int H, int W>
struct BitBoard {
    bitset<H * W> board;

   public:
    int get_H() const {
        return H;
    }
    int get_W() const {
        return W;
    }

    void set(int y, int x, bool f) {
        board[y * W + x] = f;
    }
    bool get(int y, int x) const {
        return board[y * W + x];
    }
    void flip(int y, int x) {
        board[y * W + x] = ~board[y * W + x];
    }
    void flip() {
        board.flip();
    }

    int count() const {
        return board.count();
    }
    bool test() const {
        return board.test();
    }
    bool all() const {
        return board.all();
    }
    bool any() const {
        return board.any();
    }
    bool none() const {
        return board.none();
    }

    bool operator==(const BitBoard<H, W>& other) const {
        return board == other.board;
    }
    bool operator!=(const BitBoard<H, W>& other) const {
        return !(board == other.board);
    }
    BitBoard<H, W>& operator|=(const BitBoard<H, W>& other) {
        board |= other.board;
        return *this;
    }
    BitBoard<H, W>& operator&=(const BitBoard<H, W>& other) {
        board &= other.board;
        return *this;
    }
    BitBoard<H, W>& operator^=(const BitBoard<H, W>& other) {
        board ^= other.board;
        return *this;
    }
    BitBoard<H, W> operator~() {
        BitBoard<H, W> ret = *this;
        ret.board.flip();
        return ret;
    }
};

template <int H, int W>
ostream& operator<<(ostream& os, const BitBoard<H, W>& bb) {
    for (int i = 0; i < bb.get_W() + 2; i++) {
        if (i == 0 || i == bb.get_W() + 1) {
            os << "+";
        } else {
            // os << "-";
            os << (i - 1) % 10;
        }
    }
    os << endl;
    for (int i = 0; i < bb.get_H(); i++) {
        // os << "|";
        os << i % 10;
        for (int j = 0; j < bb.get_W(); j++) {
            os << (bb.get(i, j) ? "#" : ".");
        }
        os << "|" << endl;
    }
    for (int i = 0; i < bb.get_W() + 2; i++) {
        if (i == 0 || i == bb.get_W() + 1) {
            os << "+";
        } else {
            os << "-";
        }
    }
    return os;
}

template <int H, int W>
class BitBoardUtils {
    bitset<H * W> mask_left, mask_right;

    void make_mask() {
        for (int y = 0; y < H; y++) {
            mask_left |= bitset<H * W>(1) << (y * W);
            mask_right |= bitset<H * W>(1) << (y * W + W - 1);
        }
        mask_left = ~mask_left;
        mask_right = ~mask_right;
    }

   public:
    BitBoardUtils() {
        make_mask();
    }

    void shift_up(BitBoard<H, W>& board) {
        board.board >>= W;
    }
    void shift_down(BitBoard<H, W>& board) {
        board.board <<= W;
    }
    void shift_left(BitBoard<H, W>& board) {
        board.board = (board.board & mask_left) >> 1;
    }
    void shift_right(BitBoard<H, W>& board) {
        board.board = (board.board & mask_right) << 1;
    }
    // boardの位置から上下左右に1マス移動できる場所
    // 注意: 元の位置は含まないので、含むようにしたい場合はorを取る
    void expand(BitBoard<H, W>& board) {
        BitBoard<H, W> bb_up = board;
        shift_up(bb_up);
        BitBoard<H, W> bb_down = board;
        shift_down(bb_down);
        BitBoard<H, W> bb_left = board;
        shift_left(bb_left);
        BitBoard<H, W> bb_right = board;
        shift_right(bb_right);
        board.board = bb_up.board | bb_down.board | bb_left.board | bb_right.board;
    }
};

Usage

int main() {
    constexpr int H = 15, W = 20;
    using Board = BitBoard<H, W>;
    using BoardUtils = BitBoardUtils<H, W>;
    Board board;
    BoardUtils board_utils;

    // board.set(5, 15, true);
    // board.set(5, 14, true);

    board_utils.expand(board);
    board_utils.expand(board);

    cout << board << endl;

    cout << sizeof(board) << endl;
    return 0;
}

Verified

  • なし