반응형
문제
소풍 때 서로 친구인 학생들끼리만 짝을 지어야 합니다. 각 학생들의 쌍에 대해 이들이 서로 친구인지 여부가 주어질 때, 학생들을 짝 지을 수 있는 방법의 수를 계산하는 프로그램을 작성하세요. 짝이 되는 학생들이 일부만 다르더라도 다른 방법이라고 봅니다.(태연 제시카)(써니 티파니)(효연 유리)
(태연 제시카)(써니 유리)(호연 티파니) --> 다른경우
- 입력
- 테스트 케이스의 수 C (C<=50) 가 주어집니다.
- 첫줄에는 학생의 수 n (2<=n<=10) 친구 쌍의 수 m (0<= m <= n(n-1)/2)
- 그 다음줄에 m개의 정수 쌍으로 서로 친구인 두 학생의 번호 (0부터 n-1사이의 정수)
풀이
- 친구 쌍을 2차원 배열 friendList[ ] [ ]에 저장 , [a] [b] 가 친구면 true를 넣어둠. / [b] [a] 역시 마찬가지
- 학생의 수(n) 만큼 ArrayList형 friendsCheck에 1저장 (1 = 친구 쌍이 없음 / 99 = 친구 쌍 있음)
- 재귀 함수 isFriend (index, friendList[] [])
- index를 0부터 n까지 탐색 n까지 도달했으면 성공 (친구를 끝까지 다 찾음)
- 만약에 현재 인덱스에 있는 애 (friendsCheck 에서 index 주소에 해당하는 애) 가 친구 쌍이 있으면
다음 인덱스 애를 탐색 - 현재 인덱스에 해당하는 애가 친구가 없으면, 그 인덱스랑 친구인 애들을 다 탐색해봄
- 이때 친구인 애 찾으면 친구 쌍을 만들고, 다음 인덱스로 넘어감.
*이때 다시 돌아와서 다른 경우의 수도 찾아봐야 함으로, 다음 재귀함수 호출 후 직전 꺼 초기화
학생의 수(n) 만큼 ArrayList형 friendsCheck에 1저장 (1 = 친구 쌍이 없음 / 99 = 친구 쌍 있음)
ex) 0이랑 친구인 애 -> 1이 친구임 (0,1) -> 1은 이미 친구쌍 있으니깐 2랑 친구인 애 -> 3이 친구임(0,1) (2,3)
->3은 이미 친구쌍 있으니깐 4랑 친구인 애 -> 5랑 친구임 (0,1)(2,3)(4,5) -> 5까지 왔으니깐 정답
다시 돌아가서 2랑 친구인 두번째 애 -> 4가 친구임 (0,1) (2,4) >>..
다시 크게 돌아가서 0이랑 친구인 두번째 애 -> 2가 친구임 (0,2) >>...
코드 (JAVA)
import java.util.ArrayList;
import java.util.Scanner;
public class PICNIC {
static int n;
static int ans;
static ArrayList<Integer> friendsCheck = new ArrayList<>();
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int C = sc.nextInt();
int result[] = new int[C];
sc.nextLine();
for(int i = 0; i<C; i++){
ans = 0;
n = sc.nextInt();
//친구쌍이 맺어졌는지를 체크하는 리스트 선언
for(int j=0; j<n; j++){
friendsCheck.add(j,1);
}
int m = sc.nextInt();
sc.nextLine();
boolean friendList[][] = new boolean[10][10];
for(int j =0; j<m; j++){
int a = sc.nextInt();
int b = sc.nextInt();
//친구 리스트에 친구라고 표시해두기.
friendList[b][a] = true;
friendList[a][b] = true;
}
//0부터 재귀함수 실행
isFriend(0,friendList);
result[i] = ans;
}
for(int i = 0; i<C; i++){
System.out.println(result[i]);
}
}
//n = 학생 수 m = 친구 쌍, index = list에서의 좌표. 직전에 몇번까지 찾아봤나 넘겨줌.
public static void isFriend(int index, boolean friendList[][]){
//숫자 끝까지 다 했으면 1번 완료
if(index == n){
System.out.println("한번 성공");
ans = ans +1;
return;
}
//만약 이미 얘가 짝이 있는경우 다음 애 탐색
if(friendsCheck.get(index) == 99){
isFriend(index+1,friendList);
return;
}
for(int i = index+1; i<n; i++){
//무조건 0이랑 친구인애 찾는거부터 시작. -> 시작할때 index가 0이므로
if((friendsCheck.get(i) == 1) && (friendList[index][i] == true)){
//만약에 짝 찾으면 해당하는 arraylist 자리에 1대신 99넣기
friendsCheck.remove(i);
friendsCheck.add(i, 99);
isFriend(index+1,friendList); // 다음 친구 탐색
//직전에 했던 친구는 다시 돌아와서 탐색해야 함으로 초기화
friendsCheck.remove(i);
friendsCheck.add(i,1);
}
}
}
}
복기
처음에 친구 쌍 위주로 조합을 만든 뒤 arraylist에 쌍이 맺어진 인원들을 삭제해가면서 조합을 만들려고 함
-> 근데 그러면 한가지 조합씩만 만들고 다음으로 넘어가버림.
-> 매 친구 쌍 마다 가능한 조합들로 하려 했으나, 중복되는 경우를 제외시키는걸 구현하기 어려움.
-> 그래서 사람 위주로 생각함.
2020.02.11
반응형
'알고리즘 > 문제풀이' 카테고리의 다른 글
책 페이지 (백준 1019번) (0) | 2020.07.09 |
---|---|
쿼드 트리 (백준 1992번) (0) | 2020.07.07 |
알약 (백준 4811번) (0) | 2020.07.07 |
시계 맞추기 [알고스팟] (ID : CLOCKSYNC) (0) | 2020.07.07 |
게임판 덮기 [알고스팟] (ID : BOARDCOVER) (0) | 2020.07.07 |
Comment