18429번: 근손실
웨이트 트레이닝을 좋아하는 어떤 대학원생은, 현재 3대 운동 중량 500의 괴력을 소유하고 있다. 다만, 하루가 지날 때마다 중량이 K만큼 감소한다. 예를 들어 K=4일 때, 3일이 지나면 중량이 488로
www.acmicpc.net
boj의 근손실 문제를 풀며, 처음으로 Java에서 순열을 구현해보게 되었다.
따라서 순열의 구현을 공부하는 김에, 순열/조합/부분집합까지 공부하였다.
순열(Permutation)
순열의 경우, 순서를 신경써주어야 한다.
(1,2) != (2,1) 이다.
아래는 nPr을 구현한 코드이다.
package 완전탐색.permutation;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
static int N, R; //nPr
static int totalCnt = 0; //경우의수
static boolean[] isSelected;
public static void main(String[] args) throws IOException {
BufferedReader br =new BufferedReader(new InputStreamReader(System.in));
N = Integer.parseInt(br.readLine());
isSelected = new boolean[N];
permutation(0);
System.out.println(totalCnt);
}
private static void permutation(int index){
if(index == R){
totalCnt++; //경우의 수 1 증가
return;
}
for(int i = 0; i<N; i++){
//중복 체크
if(isSelected[i]) continue;
isSelected[i] = true;
permutation(index+1);
isSelected[i] = false;
}
}
}
조합(Combination)
조합의 경우, 순서를 신경쓰지 않아도 된다.
(1,2) == (2,1)이다.
다음은 nCr의 경우의수를 구현한 코드이다.
순서를 신경쓰지 않아도 되므로, isSelected배열을 사용하지 않고, 선택한 다음 인덱스부터 for문으로 재귀해주면 된다.
import java.io.*;
import java.util.*;
public class Main{
//N개 중 R개 뽑음
static int totalCnt = 0; //경우의수
static int N,R; //숫자 개수, 한 조합의 개수
public static void main(String[] args) throws IOException {
BufferedReader br =new BufferedReader(new InputStreamReader(System.in));
N = Integer.parseInt(br.readLine());
R = Integer.parseInt(br.readLine());
combination(0,0);
System.out.println(totalCnt);
}
private static void combination(int index,int start) {
if(index==R) {
totalCnt++;
return;
}
for (int i=start ; i<N ; i++) {
combination(index+1, i+1);
}
}
}
부분집합(PowerSet 또는 SubSet)
N개의 원소가 있는 집합에서, 부분집합의 개수를 구하는 경우이다.
해당 인덱스의 원소를 포함하는가, 포함하지 않는가를 나누어서 재귀해주면 된다.
import java.io.*;
import java.util.*;
public class Main{
static int totalCnt = 0; //경우의수
static int N; //숫자 개수
static boolean[] isSelected;
public static void main(String[] args) throws IOException {
BufferedReader br =new BufferedReader(new InputStreamReader(System.in));
N = Integer.parseInt(br.readLine());
isSelected = new boolean[N];
generateSubSet(0);
System.out.println(totalCnt);
}
private static void generateSubSet(int index) {
if(index ==N) {
// 부분집합 완성
totalCnt++;
return;
}
// 현재 원소를 부분집합에 넣기
isSelected[index] = true;
generateSubSet(index+1);
// 현재 원소를 부분집합에 넣지 않기
isSelected[index]= false;
generateSubSet(index+1);
}
}
각 코드에 원하는 조건을 추가해서 전체 경우의 수를 탐색할 수 있다.
출처)
[알고리즘 개념] 순열 조합 부분집합(순조부~)
자바로 알고리즘을 풀면서 순조부에 대해서 깊게 공부해야했습니다... (파이썬은 api가 있지만 자바는 없기 때문에) 순조부를 공부하면서 자신이 없던 재귀도 공부하구,,, 의외로 문제 풀때 개념
kwangkyun-world.tistory.com
'Java알고리즘' 카테고리의 다른 글
[BOJ][Java]Q2174 - 로봇 시뮬레이션 (0) | 2022.04.05 |
---|---|
[BOJ][Java]Q18429 - 근손실 (0) | 2022.04.05 |
[BOJ][Java]Q15591 - MooTube (0) | 2022.03.16 |
[BOJ][Java]Q1918 - 후위 표기식 (0) | 2022.03.15 |
[BOJ][Java]Q4256 - 트리(전위순회,중위순회로 후위순회 구하기) (0) | 2022.03.14 |