https://swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AV4suNtaXFEDFAUf



문제 조건에 따라서 이미 전원이 들어와있는 코어를 제외한 모든 코어를, 모든 경우로 전원을 연결시켜주면서 만족하는 경우를 찾아주면 된다.



다만, DFS를 진행할 때, 어떠 코어에서, 4방향 어디로도 연결할 수 없어도, 전원에 연결하지 않고 다음 코어에 대한 탐색을 이어갈 수 있도록 처리해야한다.


일반적인 백트래킹이나 DFS에 더해서, 어디에도 연결되지 않는 경우 이어서 탐색하도록 구현해주면 된다.



가령 1 2 3 4 의 코어가 있다고 가정하면, 2번이 어디에도 연결될 수 없더라도, 2번을 제외한 1 3 4가 모두 전원이 들어와서, 답안으로 포함되는 경우가 있을 수 있기 때문에 이 부분도 고려해야 한다.




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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
typedef pair<intint> pii;
 
int map[13][13], n;
bool con[13];
vector<pii> v;
 
int pwrCnt = 0, st = 0;
 
 
pii makeWire(pii pos, int dir) { //동서남북 0123
    int len = 0;
 
    if (dir == 0) {
        for (int j = pos.second + 1; j < n; j++) {
            if (map[pos.first][j] != 0)
                return {00};
        }
        for (int j = pos.second + 1; j < n; j++) {
            map[pos.first][j] = 1;
            len++;
        }
        
    }
    else if (dir == 1) {
        for (int j = pos.second - 1; j >= 0; j--) {
            if(map[pos.first][j] != 0)
                return { 00 };
        }
        for (int j = pos.second - 1; j >= 0; j--) {
            map[pos.first][j] = 1;
            len++;
        }
    }
    else if (dir == 2) {
        for (int i = pos.first + 1; i < n; i++) {
            if (map[i][pos.second] != 0)
                return { 00 };
        }
        for (int i = pos.first + 1; i < n; i++) {
            map[i][pos.second] = 1;
            len++;
        }
        
    }
    else {
        for (int i = pos.first -1 ; i >= 0; i--) {
            if (map[i][pos.second] != 0)
                return { 00 };
        }
        for (int i = pos.first - 1; i >= 0; i--) {
            map[i][pos.second] = 1;
            len++;
        }
    }
 
    return {1, len};
}
 
void removeWire(pii pos, int dir) {
    if (dir == 0
        for (int j = pos.second + 1; j < n; j++)
            map[pos.first][j] = 0;
 
    else if (dir == 1
        for (int j = pos.second - 1; j >= 0; j--)
            map[pos.first][j] = 0;
            
    else if (dir == 2
        for (int i = pos.first + 1; i < n; i++
            map[i][pos.second] = 0;
        
    else     
        for (int i = pos.first - 1; i >= 0; i--
            map[i][pos.second] = 0;
            
}
 
int tot = 0;
int Max = 0;
bool neverChosen = true;
vector<int> lenCandi;
void dfs(int k, int conCnt) {
    if (k == (int)v.size()) {
        
        if (Max < conCnt) {
            Max = conCnt;
            lenCandi.clear();
            lenCandi.push_back(tot);
        }
        else if (Max == conCnt) 
            lenCandi.push_back(tot);
        
        return;
    }
 
    //지금까지 연결한것 + 앞으로 연결할 수 있는거 < Max라면 할 필요가없음
    if (conCnt + (v.size() - k) < Max) return;
 
    if (k == 0) st = 0;
    for (int i = st; i < v.size(); i++) {
        if (con[i]) continue;
        neverChosen = true;
        for (int j = 0; j < 4; j++) {
            pii res = makeWire(v[i], j);
            
            if (res.first == 1) { //연결가능
                neverChosen = false;
                con[i] = true;
            //    printf("%d 연결됨 %d쪽 깊이 %d\n", i, j, k);
                tot += res.second; //길이
                st = i;
                dfs(k + 1, conCnt+1);
                removeWire(v[i], j);
                con[i] = false;
                tot -= res.second;
            }
            
            if (j == 3 && neverChosen) { //4방으로 모두 연결할수 없는 지점
                st = i;
                dfs(k + 1, conCnt);
            }
 
        }
    }
}
 
int main(void) {
    //setbuf(stdout, NULL);
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
 
    int T;
    cin >> T;
    for (int t = 1; t <= T; t++) {
        cin >> n;
 
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                cin >> map[i][j];
                if (map[i][j] == 1) {
                    if (i == 0 || j == 0)
                        pwrCnt++//자동 전원 연결 상태
                    else
                        v.push_back({ i, j });
                }
            }
        }
 
        dfs(00);
 
        sort(lenCandi.begin(), lenCandi.end());
        if (lenCandi.size() == 0) lenCandi.push_back(0);
        cout << "#" << t << ' ' << lenCandi[0<< '\n';
        //초기화
        v.clear();
        pwrCnt = 0;
        tot = 0;
        Max = 0;
        lenCandi.clear();
        neverChosen = true;
    }
 
    return 0;
}
 
cs


+ Recent posts