let menu = ["Home", "Algorithms", "CodeHub", "VNOI Statistics"];

Overview

COWGIRL - Cô gái chăn bò

solution.md

Giả sử \(M \ge N\), ta có \(M \times N \le 30\), suy ra \(N \le 5\).

Vì N khá nhỏ nên ta có thể QHĐ trạng thái như sau:

Gọi \(F[i][x]\) là số cách để sắp xếp bò từ hàng \(1\) đến hàng \(i\), với hàng \(i\) có trạng thái có bò/không có bò là \(x\).

Vì mỗi hàng có tối đa \(N\) con bò nên trạng thái \(x\) chạy từ \(0\) đến \(2^N-1\).

Tính \(F[i][x]\) như sau: duyệt tất cả các trạng thái \(y\) mà có thể nằm trước \(x\) và không vi phạm yêu cầu đề bài (bò không tạo thành hình vuông 2x2 và không có hình vuông 2x2 trống), \(F[i][x] = F[i][x] + F[i-1][k]\).

main.cpp
Open in Github Download
#include <iostream>
using namespace std;

#define ll long long
#define for(i,a,b) for (int i=a; i<b; i++)

bool check(int a, int b, int s) {
    int x = a & b;
    int y = (~a & ~b) & s-1;
    return !(x & x>>1) && !(y & y>>1);
}

ll solve(int m, int n) {
    int s = 1<<n;
    ll f[m][s];
    for(i,0,s) f[0][i] = 1;

    for(i,1,m) for(j,0,s) {
        f[i][j] = 0;
        for(k,0,s) if (check(j,k,s)) {
            f[i][j] += f[i-1][k];
        }
    }

    ll res = 0;
    for(i,0,s) res += f[m-1][i];
    return res;
}

int main() {
    ios::sync_with_stdio(false); cin.tie(0);
    int T; cin >> T;
    while (T--) {
        int m, n;
        cin >> m >> n;
        cout << solve(max(m, n), min(m, n)) << '\n';
    }
    return 0;
}
Comments