-
[BOJ] 14889 스타트와 링크알고리즘/BOJ 2020. 7. 26. 03:48
https://www.acmicpc.net/problem/14889
14889번: 스타트와 링크
예제 2의 경우에 (1, 3, 6), (2, 4, 5)로 팀을 나누면 되고, 예제 3의 경우에는 (1, 2, 4, 5), (3, 6, 7, 8)로 팀을 나누면 된다.
www.acmicpc.net
아이디어
방법1 dfs를 이용하여 팀이 될 수 있는 모든 경우의 수를 구한 다음 능력치의 차이를 계산
- 기존 시작 시에는 다들 0번 팀이라고 배치하고 팀을 부여함
- 재귀문을 통하여 한사람씩 1번 팀을 경우의 수마다 부여를 하고 해당 인원의 반이 1번팀의 배치가 되었으면 능력치 차이를 계산
방법2 비트 마스킹 방법을 이용하여 팀을 구분한 다음 능력치의 차이를 계산
-예시 : 110100
- 오른쪽부터 왼쪽 순으로 사람의 번호가 1번부터 시작된다고 생각 후 0이면 0번팀, 1이면 1번팀에 배정이 되았다고 생각
- 1,2,4,번 사람은 0번팀 / 3,5,6번 사람은 1번팀
- 위와 같이 판단 후 능력치의 차이를 계산
소스코드
방법1
#include <cstdio> #include <vector> #include <cmath> using namespace std; int num; int map[21][21]; int diff = -1; int team[21]; void dfs(int team_cnt, int start) { //쌍이 지어지면 그 차이를 구함 if (team_cnt == (num / 2)) { int sum1 = 0; int sum2 = 0; int temp_diff; vector<int> team1; vector<int> team2; for (int i = 0; i < num; i++) { if (team[i] == 0) { team1.push_back(i); } else if (team[i] == 1) { team2.push_back(i); } } int s1 = team1.size(); int s2 = team2.size(); for (int i = 0; i < s1; i++) { for (int j = i + 1; j < s1; j++) { sum1 += (map[team1[i]][team1[j]] + map[team1[j]][team1[i]]); } } for (int i = 0; i < s2; i++) { for (int j = i + 1; j < s2; j++) { sum2 += (map[team2[i]][team2[j]] + map[team2[j]][team2[i]]); } } temp_diff = abs(sum1 - sum2); if (diff == -1 || temp_diff < diff) { diff = temp_diff; } return; } for (int i = start + 1; i < num; i++) { team[i] = 1; dfs(team_cnt + 1, i); team[i] = 0; } } int main() { scanf("%d", &num); for (int i = 0; i < num; i++) { for (int j = 0; j < num; j++) { scanf("%d", &map[i][j]); } } dfs(0, -1); printf("%d\n", diff); return 0; }
방법2
#include <cstdio> #include <vector> #include <cmath> using namespace std; int num; int map[21][21]; int diff = -1; vector<int> team1; vector<int> team2; void set_team(int group) { for (int i = 0; i < num; i++) { if (group % 2 == 0) { team1.push_back(i); } else { team2.push_back(i); } group = group >> 1; } } void calc_diff() { int s1 = team1.size(); int s2 = team2.size(); int sum1 = 0; int sum2 = 0; int temp_diff; for (int i = 0; i < s1; i++) { for (int j = i + 1; j < s1; j++) { sum1 += (map[team1[i]][team1[j]] + map[team1[j]][team1[i]]); } } for (int i = 0; i < s2; i++) { for (int j = i + 1; j < s2; j++) { sum2 += (map[team2[i]][team2[j]] + map[team2[j]][team2[i]]); } } temp_diff = abs(sum1 - sum2); if (diff == -1 || temp_diff < diff) { diff = temp_diff; } } int main() { scanf("%d", &num); for (int i = 0; i < num; i++) { for (int j = 0; j < num; j++) { scanf("%d", &map[i][j]); } } for (int i = 0; i < pow(2, num); i++) { team1.clear(); team2.clear(); set_team(i); if (team1.size() != num / 2) continue; calc_diff(); } printf("%d\n", diff); return 0; }
'알고리즘 > BOJ' 카테고리의 다른 글
[BOJ] 14891번 톱니바퀴 (0) 2020.07.30 [BOJ] 14890번 경사로 (0) 2020.07.26 [BOJ] 14888 연산자 끼워넣기 (0) 2020.07.26 [BOJ] 11055번 가장 큰 증가 부분 수열 (0) 2020.07.11 [BOJ]11053번 가장 긴 증가하는 부분 수열 (0) 2020.07.11