반응형
Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- 알고리즘
- 타입 챌린지
- HTTP 완벽 가이드
- 백준
- 크롤링
- 가천대
- 그래프
- 소켓
- socket
- TCP
- ip
- 프로그래머스
- 문자열
- Node.js
- 타입스크립트
- Algorithm
- HTTP
- 레벨 1
- 수학
- Nestjs
- typescript
- dfs
- javascript
- type challenge
- dp
- 프로그래머스 레벨 2
- 쉬운 문제
- 자바스크립트
- BFS
- Crawling
Archives
- Today
- Total
kakasoo
[백트래킹] 스타트와 링크 (백준 14889번) 본문
반응형
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
|
#include <iostream>
using namespace std;
int startLink[21];
int arr[21][21];
int visited[21];
int n;
void dfs(int cnt, int start)
{
if (cnt == n / 2)
{
for (int i = 0; i < n / 2; i++)
cout << startLink[i] << ' ';
cout << endl;
return;
}
for (int i = start + 1; i <= n; i++)
{
if (!visited[i])
{
visited[i] = true;
startLink[cnt] = i;
dfs(cnt + 1, i);
visited[i] = false;
}
}
}
int main(void)
{
cin >> n;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
cin >> arr[i][j];
dfs(0, 0);
}
|
실행 결과는 아래와 같다.
내용이 길어서 잘리긴 했지만, 만약 n = 8인 형태의 arr를 입력하게 된다면,
중복이 없는 오름차순으로 1 2 3 4 부터 5 6 7 8 까지 출력한다.
이렇게 만든 이유는, 만약 n/2 (이 경우에는 4)의 값만큼 startTeam에 넣을 수 있다면,
나머지는 자동으로 linkTeam이 될 것이기 때문이다.
아래는 위의 dfs 함수를 수정하여 만든 정답이다.
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
|
#include <iostream>
using namespace std;
int startLink[21];
int arr[21][21];
int visited[21];
int n;
int minV = 987654321;
void dfs(int cnt, int start)
{
if (cnt == n /2 )
{
int sumA = 0, sumB = 0;
for (int i = 0; i < n / 2; i++)
{
for (int j = i + 1; j < n / 2; j++)
{
sumA += (arr[startLink[i]][startLink[j]] + arr[startLink[j]][startLink[i]]);
}
}
// sumA는 start팀의 점수를 구하는 것.
int link[21];
// link 팀의 점수를 구하기 위해서 link팀 배열을 만들고, start 팀에 없는 사람을 넣는다.
// 아래의 반복문이 cnt가 n/2인 시점에서 방문하지 않은 곳들을 찾아 배열에 대입해준다.
int cur = 0;
for (int i = 1; i <= n; i++)
{
if (!visited[i])
link[cur++] = i;
}
for (int i = 0; i < n / 2; i++)
{
for (int j = i + 1; j < n / 2; j++)
{
sumB += (arr[link[i]][link[j]] + arr[link[j]][link[i]]);
}
}
// 마찬가지로 sumB는 link팀의 점수를 구하는 것.
if (minV > abs(sumA - sumB)) minV = abs(sumA - sumB);
// if (minV == 0) { cout << 0; return 0;} 로 끝내버려도 된다.
return;
}
for (int i = start + 1; i <= n; i++)
{
if (!visited[i])
{
visited[i] = true;
startLink[cnt] = i;
dfs(cnt + 1, i);
visited[i] = false;
}
}
// 전형적인 n과 m 코드다.
// dfs의 매개변수로는 현재 start팀에 입력된 멤버의 숫자와 탐색 시작점이다.
// dfs의 두번째 매개변수로 i를 넣은 것을 볼 수 있을 텐데,
// 이 두번째 매개변수 덕분에 오름차순으로 삽입이 진행된다.
}
int main(void)
{
cin >> n;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
cin >> arr[i][j];
dfs(0, 0);
cout << minV;
}
|
느낀점
풀다가 죽을 뻔 했는데, n과 m 문제가 생각난 것이 신의 한수였다.
dfs임에도 계속 중복이 나왔던 이유를 다음과 같이 생각해볼 수 있겠다.
1) dfs를 2갈래 나눠서 start팀에 대입한 경우와 link팀에 대입한 경우를 구한 것, 결국 분화된다.
2) 시작점을 따로 명시하지 않은 점. (1 2 3 4를 7~8번 정도 하여 시간초과 발생.)
해결책은 dfs식을 하나로 통합하고, 탐색 시작 지점을 dfs의 두번째 매개변수로 전달한 것.
신의 한수였다고 잘도 말했지만, 정말로 머리에 한계가 왔다.
지금의 이 짜릿함이 없다면, 내일 아마 코딩에 손도 못댔을 것이다.
문제를 풀고자 지금까지 매달린 게 다행이다, 코딩에 정 떨어지기 전에 오늘은 빨리 관두자.
반응형
'프로그래밍 > 알고리즘 풀이' 카테고리의 다른 글
[greedy] 회의실 배정 (백준 1931번) (0) | 2020.03.03 |
---|---|
[bfs] 양 (백준 3184번) (0) | 2020.03.03 |
[백트래킹] 스도쿠 (백준 2580번) (2) | 2020.03.01 |
[이분 탐색] 랜선 자르기 (백준 1654번) (0) | 2020.03.01 |
[이분탐색] 숫자 카드2 (백준 10816번) (0) | 2020.02.21 |