2629번: 양팔저울
첫째 줄에는 추의 개수가 자연수로 주어진다. 추의 개수는 30 이하이다. 둘째 줄에는 추의 무게들이 자연수로 가벼운 것부터 차례로 주어진다. 같은 무게의 추가 여러 개 있을 수도 있다. 추의 무
www.acmicpc.net
0. 최대 무게 500g인 추가 최대 30개 들어오므로, 최대 탐색 가능 범위는 -15000 ~ 15000
1. 추를 올리지 않는 경우, 물건의 반대편에 올리는 경우(+), 물건쪽에 올리는 경우(-) 3가지 경우를
모든 추에 대해 재귀로 진행하며, 이 과정에서 거치는 모든 무게를 true로 표시한다.
- 이때, 추를 추가한 무게가 앞 재귀에서 나왔던 무게일 경우, 중복 연산이 발생하므로 진입하지 않는다 (가지치기)
2. 물건의 무게를 입력받고, 15000초과의 무게일 경우 즉시 N을, 그 이하일 경우 true/false 값에 따라 Y/N을 출력해준다.
추가적으로 생각해본 개선점
1. dfs처럼 재귀를 돌며 깊은 단계에 진입 때문에, 깊은 단계에서 possible 배열이 수정되어도
얕은 단계에 영향을 주지 못하도록 possible배열이 2중으로 구현되어야 했음.
- bfs처럼 큐에 넣어가며 단계별로 작업했다면 possible 배열 하나로 가능하지 않았을까?
2. -7500 값은 적어도 500g추 15개가 있어야 도달 가능한 값이므로,
나머지 추 15개를 전부 +로 설정해도 0이상의 값을 가질 수 없다.
- -7500 ~ 15000으로 possible 배열을 사용하면 크기를 25%정도 절약할 수 있었음.
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main {
static int num;
static int[] weight;
static boolean[][] possible;
public static void main(String[] args)throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringBuffer sb = new StringBuffer();
num=Integer.parseInt(br.readLine());
weight = new int[num];
//추 무게 입력
StringTokenizer st = new StringTokenizer(br.readLine());
for (int i = 0; i < num; i++) {
weight[i]=Integer.parseInt(st.nextToken());
}
//해당무게의 표현 가능 여부 표시를 위한 boolean배열
//추는 500g이하, 30개이하이므로, 최대 +15000, 최소 -15000까지 탐색할 수 있다
//15000 지점을 가상의 0으로 가정, 30001개의 배열로 선언한다.
possible = new boolean[30001][num];
//추에 대한 선택지는 3가지 - 올리지 않는다|구슬쪽에 올린다|반대편에 올린다
//3가지 선택지를 탐색하며 모든 계산 가능한 경우를 true로 마크한다
search(0, 15000);//초깃값은 가상의 0인 15000
//구슬의 개수 입력받기
int ball_num = Integer.parseInt(br.readLine());
st = new StringTokenizer(br.readLine());
for (int i = 0; i < ball_num; i++) {
int ball_weight = Integer.parseInt(st.nextToken());
//최대 무게인 15000을 넘으면 바로 N
if(ball_weight>15000) {
sb.append("N ");
}
//해당 무게가 가능하다면 Y, 아니면 N을 기록한다.
else sb.append(possible[ball_weight+15000][num-1]?"Y ":"N ");
}
System.out.println(sb);
}
static void search(int cnt, int cur) {
//모든 추에 대해 탐색 종료
if(cnt==num) {
return;
}
else {
//해당 무게에 도달한 적 없다면 진입한다
if(!possible[ cur+weight[cnt] ][cnt]) {
possible[ cur+weight[cnt] ][cnt]=true;
search(cnt+1, cur+weight[cnt]);
}
//해당 무게에 도달한 적 없다면 진입한다
if(!possible[ cur-weight[cnt] ][cnt]) {
possible[ cur-weight[cnt] ][cnt]=true;
search(cnt+1, cur-weight[cnt]);
}
//올리지 않는다
possible[cur][cnt]=true;
search(cnt+1, cur);
}
}
}
'알고리즘 문제 풀이 > BOJ 골드' 카테고리의 다른 글
[백준] 15686 - 치킨 배달 (0) | 2021.04.15 |
---|---|
[백준] 9935 - 문자열 폭발 (0) | 2021.04.14 |
[백준] 1019 - 책 페이지 (0) | 2021.04.13 |
[백준] 1566 - P배열 (0) | 2021.04.13 |
[백준] 12865 - 평범한 배낭 (0) | 2021.04.12 |
[백준] 1504 - 특정한 최단 경로 (0) | 2021.04.12 |
[백준] 17136 - 색종이 붙이기 (0) | 2021.04.12 |