[BOJ] 33928번 나이트 오브 나이츠(Hard)

12/15/2025 · 2 min read

BOJPS

[P2] 나이트 오브 나이츠(Hard)



유량 문제에서 체스판이나 2차원 격자가 나오게 되면 주어진 2차원 격자를 이분 그래프로 모델링 할 수 있음은 잘 알려져있다.

문제에서 구하고자 하는 것은 나이트를 적절히 배치하여 최대한 많은 점수를 확보하고자 하는 것이니, 왼쪽 정점들에서 오른쪽 정점들로 갈 수 있는 칸들만 연결해준 다음에

Source -> 왼쪽 정점들(체스판에서 검은 칸), 오른쪽 정점들(체스판에서 하얀 칸) -> Sink로 놓고 max flow를 찾자.

답은 전체 board의 값 - max flow이다.

모델링이 어렵다면 아래의 코드를 참고하자.


int n, v[555][555], S;
bool bound(int x, int y){ return x < 0 or x >= n or y < 0 or y >= n; }
 
inline int id(int x, int y){ return n*x + y; }
 
void solve(){
    cin >> n;
    for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) cin >> v[i][j], S += v[i][j];
    Dinic<int> flow(n * n + 5);
    int st = n * n + 2, en = n * n + 3;
    for(int x = 0; x < n; x++){
        for(int y = 0; y < n; y++){
            if((x + y) & 1) flow.add_edge(st, id(x, y), v[x][y]);
            else flow.add_edge(id(x, y), en, v[x][y]);
            for(int d = 0; d < 8; d++){
                auto nx = x + knx[d], ny = y + kny[d];
                if(bound(nx, ny)) continue;
                if(((x + y) & 1)) flow.add_edge(id(x, y), id(nx, ny), INF);
            }
        }
    }
    cout << S - flow.maximum_flow(st, en) << "\n";
}