SW Expert Academy
SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요!
swexpertacademy.com
💡풀이💡
1. N개의 요리 중에서 N/2개의 재료를 골라 요리 A, B 만들기
N/2개를 골라 요리를 만들면, 고르지 않은 나머지 N/2개가 다른 쪽 요리의 재료가 됨! 각 요리의 합을 구하는 것이기 때문에 순서가 x
>> 따라서 조합!!
2. 요리의 재료가 완성 되었을 때(조합이 완성 되었을 때) 각 요리 맛의 최솟값 구하기
1. 입력 받기
static int[][] data;
static int N ,R;
static boolean[] v; // 완성된 조합 저장
static int min;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringBuilder sb = new StringBuilder();
int T = Integer.parseInt(br.readLine());
for(int tc=1; tc<=T; tc++) {
N = Integer.parseInt(br.readLine());
R = N/2; // N/2를 계산해서 변수에 미리 저장
data = new int[N][N];
v = new boolean [N];
min = Integer.MAX_VALUE;
for(int i=0; i<N; i++) {
StringTokenizer st = new StringTokenizer(br.readLine(), " ");
for(int j=0; j<N; j++) {
data[i][j] = Integer.parseInt(st.nextToken());
}
}
2. 요리 재료 조합 구하기
조합이 완료 되었을 때(cnt == R) 각 요리의 맛 최솟값을 계산!
- 조합이 완성 되었을 때, 선택되지 않은 나머지는 무조건 다른 요리의 재료가 되기 때문에 int형 배열로 R개 만큼 생성하지 않고 boolean형으로 N개 만큼 생성함
📌놓쳤던 포인트!
- 기존의 조합 코드에서는 완성될 조합을 저장할 배열을 R개만큼 생성해 b[cnt] = a[i] 라는 형식으로 했었다.
- 완성될 조합을 저장할 때 boolean형 배열에 선택됐는지 확인하기 때문에 v[cnt]가 아니라 v[i]로 true 체크를 해줘야 함
- v[cnt] 로 하면 cnt 최댓값이 R이기 때문에 0,1 인덱스의 재료만 선택이 됨ㅠㅠㅠ…
static void comb(int cnt, int start) {
if(cnt == R) {
// 맛 최솟값 계산하기
min = cal_flavor();
}
for(int i=start; i<N; i++) {
v[i] = true;
comb(cnt+1, i+1);
v[i] = false;
}
}
3. 맛 최솟값 계산하기
둘 다 true일 때를 A요리 , 나머지 둘 다 false일 때를 B요리 재료라고 생각하고 각각의 맛의 합 구하기
둘의 차의 최솟값을 리턴
static int cal_flavor() {
int aSum = 0;
int bSum = 0;
for(int i=0; i<N; i++) {
for(int j=i+1; j<N; j++) {
if(v[i] && v[j]) aSum += data[i][j] + data[j][i];
else if(!v[i] && !v[j]) bSum += data[i][j] + data[j][i];
}
}
int minFlavor = Math.min(min, Math.abs(aSum-bSum));
return minFlavor;
}
4. 전체 코드
package ps_0215;
import java.io.*;
import java.util.*;
public class SW4012 {
static int[][] data;
static int N ,R;
static boolean[] v;
static int min;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringBuilder sb = new StringBuilder();
int T = Integer.parseInt(br.readLine());
for(int tc=1; tc<=T; tc++) {
N = Integer.parseInt(br.readLine());
R = N/2;
data = new int[N][N];
v = new boolean [N];
min = Integer.MAX_VALUE;
for(int i=0; i<N; i++) {
StringTokenizer st = new StringTokenizer(br.readLine(), " ");
for(int j=0; j<N; j++) {
data[i][j] = Integer.parseInt(st.nextToken());
}
}
comb(0,0);
sb.append("#").append(tc).append(" ").append(min).append("\\n");
}
System.out.println(sb.toString());
br.close();
}
static void comb(int cnt, int start) {
if(cnt == R) {
// 맛 최솟값 계산하기
min = cal_flavor();
}
for(int i=start; i<N; i++) {
v[i] = true;
comb(cnt+1, i+1);
v[i] = false;
}
}
static int cal_flavor() {
int aSum = 0;
int bSum = 0;
for(int i=0; i<N; i++) {
for(int j=i+1; j<N; j++) {
if(v[i] && v[j]) aSum += data[i][j] + data[j][i];
else if(!v[i] && !v[j]) bSum += data[i][j] + data[j][i];
}
}
int minFlavor = Math.min(min, Math.abs(aSum-bSum));
return minFlavor;
}
}
'알고리즘 문제풀이 > SW Expert' 카테고리의 다른 글
[SW Expert 1953] 탈주범 검거 (0) | 2023.04.04 |
---|---|
[SW Expert 5656] 벽돌 깨기 (0) | 2023.02.25 |
[SW 1247] 최적 경로 (0) | 2023.02.23 |
[SW 1873] 상호의 배틀필드 (0) | 2023.02.23 |
[SW Expert 5215] 햄버거 다이어트 (0) | 2023.02.16 |
댓글