본문 바로가기

알고리즘 관련/BOJ

BOJ)12922 블럭 퍼즐

문제: icpc.me/12922


1x1x2 블럭이 정사각형 그리드에서 이동할 때 게임승리를 불가능하게 뚫어야하는 구멍의 수를 출력하는 문제이다.


문제에서 블럭의 이동경로를 살펴보면 시작점에서 부터 4방향으로 3칸 떨어진 지점에만 서있을 수 있다.


이를 이용하여 모든 정점에서 3칸 떨어진 지점으로 그래프를 구성해주는데 이 때 간선의 capacity는 지나가는 경로에 뚫어야하는 구멍 수가 되야되고 해당 정점에 구멍을 뚫는 경우는 정점을 분할하여 사이에 capacity를 1로 주는걸로 그래프를 모델링 해주면


src에서 sink로의 mincut을 구해주면 답을 구해낼 수 있다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <queue>
#define INF 987654321
using namespace std;
struct dinic {
    int n;
    struct Edge {
        int v, cap, rev;
        Edge(int v, int cap, int rev) :v(v), cap(cap), rev(rev) {}
    };
    vector<vector<Edge>> vt;
    vector<int> level, work;
    dinic(int n) : n(n) {
        vt.resize(n + 1);
    }
    void addEdge(int s, int e, int c) {
        vt[s].emplace_back(e, c, vt[e].size());
        vt[e].emplace_back(s, 0, vt[s].size() - 1);
    }
    bool bfs(int src, int sink) {
        queue<int> qu;
        level.assign(n + 1-1);
        level[src] = 0;
        qu.push(src);
        while (qu.size()) {
            int here = qu.front();
            qu.pop();
            for (auto next : vt[here]) {
                if (next.cap&&level[next.v] == -1) {
                    level[next.v] = level[here] + 1;
                    qu.push(next.v);
                }
            }
        }
        return level[sink] != -1;
    }
    int dfs(int here, int crtcap, int target) {
        if (here == target)return crtcap;
        for (int &= work[here]; i < vt[here].size(); i++) {
            int next = vt[here][i].v;
            int cap = vt[here][i].cap;
            if (cap&&level[here] + == level[next]) {
                int flow = dfs(next, min(cap, crtcap), target);
                if (flow) {
                    vt[here][i].cap -= flow;
                    vt[next][vt[here][i].rev].cap += flow;
                    return flow;
                }
            }
        }
        return 0;
    }
    int stream(int src, int sink) {
        int ret = 0;
        while (bfs(src, sink)) {
            work.assign(n + 10);
            while (1) {
                int flow = dfs(src, INF, sink);
                if (!flow)break;
                ret += flow;
            }
        }
        return ret;
    }
};
int n;
int dx[] = { 0,0,1,-};
int dy[] = { 1,-1,0,};
int chk(int x, int y) {
    return <= x&&< n && <= y&&< n;
}
char a[55][55];
int main() {
    scanf("%d"&n);
    dinic f(* n*+ 3);
    for (int i = 0; i < n; i++
        scanf("%s", a[i]);
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            if (a[i][j] == 'H')continue;
            else if (a[i][j] == 'b')
                f.addEdge(* n*+ 1, i*+ j, INF);
            else if (a[i][j] == '$') {
                f.addEdge(n*+ i*+ j, * n*+ 2, INF);
                for (int k = 0; k < 4; k++) {
                    int tx = i + * dx[k];
                    int ty = j + * dy[k];
                    if (chk(tx, ty)) {
                        int cap = (a[i + dx[k]][j + dy[k]] == 'b' ? 0+ (a[i + * dx[k]][j + * dy[k]] == 'b' ? 0);
                        if (a[tx][ty] == 'b'&&cap) {
                            puts("-1");
                            return 0;
                        }
                    }
                }
            }
            if (a[i][j] == '.')
                f.addEdge(i*+ j, n*+ i*+ j, 1);
            else
                f.addEdge(i*+ j, n*+ i*+ j, INF);
            for (int k = 0; k < 4; k++) {
                int tx = i + * dx[k];
                int ty = j + * dy[k];
                if (chk(tx, ty) && a[tx][ty] != 'H') {
                    int cap = (a[i + dx[k]][j + dy[k]] == '.' ? 0+ (a[i + * dx[k]][j + * dy[k]] == '.' ? 0);
                    if (a[i + dx[k]][j + dy[k]] == 'b' || a[i + * dx[k]][j + * dy[k]] == 'b')
                        cap = INF;
                    if (cap)
                        f.addEdge(n*+ i*+ j, n*tx + ty, cap);
                }
            }
        }
    }
    printf("%d\n", f.stream(* n*+ 1* n*+ 2));
    return 0;
}
cs


'알고리즘 관련 > BOJ' 카테고리의 다른 글

BOJ)2507 공주 구하기  (0) 2017.06.18
BOJ)12869 뮤탈리스크  (0) 2017.06.18
BOJ)12963 달리기  (0) 2017.06.15
BOJ)8217 유성  (1) 2017.06.14
BOJ)14434 놀이기구1  (0) 2017.06.14