λ°±μ€€ 1799 λΉ„μˆ

😞 μ–΄λ €μ›Œ

문제

μ„œλ‘œλ₯Ό μž‘μ„ 수 μ—†κ²Œ λΉ„μˆμ„ 놓을 λ•Œ, λΉ„μˆ 개수의 μ΅œλŒ“κ°’μ„ κ΅¬ν•˜λΌ.

풀이

μ‹œκ°„ 초과

λ¬΄μ‹ν•˜κ²Œ λ‹€λŒλ¦¬λŠ” ν’€μ΄λ‘œ μ‹œκ°„λ³΅μž‘λ„λŠ” O(210βˆ—10)O(2^{10*10}) 이닀.

ν•˜μ§€λ§Œ λ‚΄ ν’€μ΄λŠ” μ•„λ§ˆ 이것보닀 더 많이 λ“€μ—ˆμ„ 것이닀. μ™œλƒλ©΄ caught μ²΄ν¬ν• λ•Œ λ‹€μ‹œ λ‹€λ΄€κΈ° λ•Œλ¬Έμ— μ‹œκ°„λ³΅μž‘λ„λŠ” 이정도 O(210βˆ—10Γ—10)O(2^{10*10} \times 10) .

#include <iostream>

using namespace std;

int board[11][11], n;
int dr[] = {0, 0, -1, 1}, dc[] = {1, -1, 0, 0};
int ret = 0;

bool isRange(int r, int c) {
    return r>=0 && r<n && c>=0 && c<n;
}

bool isCaught(int r, int c, int dir) {
    int rr[] = {1, -1, 1, -1}, cc[] = {1, 1, -1, -1};
    int tr = r, tc = c;
    while(isRange(tr, tc)) {
        if(board[tr][tc]==2)
            return true;
        tr += rr[dir];
        tc += cc[dir];
    }
    return false;
}

bool isCaught(int r, int c) {
    for (int i=0; i<4; ++i) {
        if(isCaught(r, c, i))
            return true;
    }
    return false;
}

// κ·Έλƒ₯ λ‹€ 놔보면 λ˜μ§€ μ•Šμ„κΉŒ
void solve(int r, int c, int cnt) {
    for (int i=r; i<n; ++i) {
        int cc = 0;
        if(i==r+1)
            cc = c+1;
        for(int j=cc; j<n; ++j) {
            if(board[i][j] == 0 || board[i][j] == 2)
                continue;
            if(isCaught(i, j))
                continue;
            board[i][j] = 2;
            solve(i, j, cnt+1);
            board[i][j] = 1;
        }
    }
    ret = max(ret, cnt);
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cin>>n;
    for(int i=0; i<n; ++i) {
        for(int j=0; j<n; ++j) {
            cin>>board[i][j];
        }
    }
    solve(0, 0, 0);
    cout << ret;
    //std::cout << "Hello, World!" << std::endl;
    return 0;
}

λ‚˜λˆ„μ–΄μ„œ ν‘Όλ‹€

두 λΆ€λΆ„μœΌλ‘œ μͺΌκ°œμ„œ μ‹œκ°„λ³΅μž‘λ„λ₯Ό μ€„μ΄λŠ” 방법. μ΄μ œκΉŒμ§€ 많이 봀던 방법인데 μƒκ°ν•˜μ§€ λͺ»ν–ˆμ–΄ 😒

μ²΄μŠ€νŒμ—μ„œ ν•˜μ–€λΆ€λΆ„κ³Ό κ²€μ€λΆ€λΆ„μ˜ λΉ„μˆμ΄ μ ˆλŒ€ μ„œλ‘œλ₯Ό μž‘μ§€ λͺ»ν•œλ‹€λŠ” 것에 κΈ°λ°˜ν•΄μ„œ 두 λΆ€λΆ„μœΌλ‘œ λ‚˜λˆ„μ–΄ ν’€ 수 μžˆλ‹€. 이 경우 O(25βˆ—5)O(2^{5*5})

κ²Œλ‹€κ°€ caught 체크할 λ•Œ κ·Έ λŒ€κ°μ„ μ— λͺ» μ˜¨λ‹€λŠ” μ •λ³΄λ§Œ 기둝해 λ†“μœΌλ©΄ O(1)O(1) 에 μ²΄ν¬ν•˜κΈ° λ•Œλ¬Έμ— μ§„μ§œλ‘œ O(25βˆ—5)O(2^{5*5}) 이닀.

μ’‹μ•˜λ˜ 풀이 기법

  1. λŒ€κ°μ„  체크

    • / ν˜•νƒœμ˜ λŒ€κ°μ„ μ€ 같은 λŒ€κ°μ„ μ΄λΌλ©΄ r+c κ°€ κ°™λ‹€.
    • \ ν˜•νƒœμ˜ λŒ€κ°μ„ μ€ 같은 λŒ€κ°μ„ μ΄λΌλ©΄ c-r 이 κ°™λ‹€.

    c-r 이 μŒμˆ˜μΌμˆ˜λ„ 있기 λ•Œλ¬Έμ— n-1 을 λ”ν•΄μ„œ μ–‘μˆ˜λ‘œ λ§Œλ“€μ–΄μ£Όμž.

  2. β†’\rightarrow λ°©ν–₯으둜 κ²€μ‚¬ν•˜κΈ°

    κ·Έλƒ₯ μˆœμ„œλŒ€λ‘œ 검사λ₯Ό ν•œλ‹€. λ­”κ°€ λ‹¨μˆœν•œλ° μƒκ°ν•˜κΈ° νž˜λ“€λ‹€.

#include <iostream>

using namespace std;

int board[11][11], n, total = 0;
int diag1[22], diag2[22];
int ret[2];

void solve(int r, int c, int cnt, bool flag) {
    if (c >= n) {
        r++;
        c%2==0? c=1 : c=0;
    }
    if (r >= n) {
        ret[flag] = max(ret[flag], cnt);
        return;
    }
    if (board[r][c] && !diag1[c - r + n - 1] && !diag2[r + c]) {
        diag1[c - r + n - 1] = diag2[r + c] = 1;
        solve(r, c + 2, cnt + 1, flag);
        diag1[c - r + n - 1] = diag2[r + c] = 0;
    }
    solve(r, c+2, cnt, flag);
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cin >> n;
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            cin >> board[i][j];
        }
    }
    solve(0, 0, 0, 0);
    solve(0, 1, 0, 1);
    cout << ret[0] + ret[1];
    //std::cout << "Hello, World!" << std::endl;
    return 0;
}

[jungin]
Written by@[jungin]
μ•ˆλ…•ν•˜μ„Έμš”

GitHub