티스토리 뷰
목차
문제
양팔 저울과 몇 개의 추가 주어졌을 때, 이를 이용하여 입력으로 주어진 구슬의 무게를 확인할 수 있는지를 결정하려고 한다.
무게가 각각 1g과 4g인 두 개의 추가 있을 경우,
주어진 구슬과 1g 추 하나를 양팔 저울의 양쪽에 각각 올려놓아 수평을 이루면 구슬의 무게는 1g이다.
또 다른 구슬이 4g인지를 확인하려면 1g 추 대신 4g 추를 올려놓으면 된다.
구슬이 3g인 경우 아래 <그림 1>과 같이 구슬과 추를 올려놓으면 양팔 저울이 수평을 이루게 된다.
따라서 각각 1g과 4g인 추가 하나씩 있을 경우 주어진 구슬이 3g인지도 확인해 볼 수 있다.
<그림 2>와 같은 방법을 사용하면 구슬이 5g 인지도 확인할 수 있다.
구슬이 2g이면 주어진 추를 가지고는 확인할 수 없다.
추들의 무게와 확인할 구슬들의 무게가 입력되었을 때,
주어진 추만을 사용하여 구슬의 무게를 확인 할 수 있는지를 결정하는 프로그램을 작성하시오.
입력
첫째 줄에는 추의 개수가 자연수로 주어진다.
추의 개수는 30 이하이다.
둘째 줄에는 추의 무게들이 자연수로 가벼운 것부터 차례로 주어진다.
같은 무게의 추가 여러 개 있을 수도 있다.
추의 무게는 500g이하이며, 입력되는 무게들 사이에는 빈칸이 하나씩 있다.
세 번째 줄에는 무게를 확인하고자 하는 구슬들의 개수가 주어진다. 확인할 구슬의 개수는 7 이하이다.
네 번째 줄에는 확인하고자 하는 구슬들의 무게가 자연수로 주어지며, 입력되는 무게들 사이에는 빈 칸이 하나씩 있다.
확인하고자 하는 구슬의 무게는 40,000보다 작거나 같은 자연수이다.
출력
주어진 각 구슬의 무게에 대하여 확인이 가능하면 Y, 아니면 N 을 차례로 출력한다.
출력은 한 개의 줄로 이루어지며, 각 구슬에 대한 답 사이에는 빈칸을 하나씩 둔다.
풀이
주어진 추로 주어진 구슬의 무게를 만들 수 있는지 여부를 판별하는 문제이다.
이 문제를 해결하기 위해서는 우선 주어진 추로 만들 수 있는 모든 문제를 먼저 구해 배열을 채우고,
그 안에 주어진 구슬의 무게가 존재하는지 확인하면 된다.
주어지는 무게 추의 개수가 최대 30개이기 때문에, DP를 사용해 추를 하나씩 추가하면서
해당 추까지 추가된 추들로 만들 수 있는 무게를 배열에 채우면 된다.
코드 구현 순서는 아래와 같다.
- 주어진 모든 입력값을 받고 추의 무게를 저장할 weight 배열을 길이 31로, 이중 배열 dp를 [31][40001]로 초기화한다.
- 이어서 먼저 주어진 추의 무게를 weight 배열에 저장하고, dp[0][0] = true, dp[0][weight[0]] = true로 초기화한다.
이는 첫 번째 추만으로 만들 수 있는 무게는 0와 첫 번째 추의 무게이기 때문이다. - 다음으로 dp배열을 채워나간다. 추를 하나씩 순회하면서 각 추를 사용해서 만들 수 있는 모든 무게의 조합을 확인한다.
만약 이전 단계에서 해당 무게를 만들 수 있는 경우(dp[i - 1][j] = true)는, 해당 무게에 현재 추의 무게를 더하거나
뺀 결과로도 도달할 수 있다는 의미이다. - 마지막으로 주어진 구슬을 순회하며 해당 무게가 dp에 저장되어있는지 확인하고 결과에 'Y' 혹은 'N'을 추가한다.
Java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Prob2629 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
int[] weights = new int[31];
boolean[][] dp = new boolean[31][40001];
StringTokenizer st = new StringTokenizer(br.readLine());
for (int i = 0; i < n; i++) {
weights[i] = Integer.parseInt(st.nextToken());
}
dp[0][0] = true;
dp[0][weights[0]] = true;
for (int i = 1; i < n; i++) {
for (int j = 0; j <= 40000; j++) {
if (dp[i - 1][j]) {
dp[i][j] = true;
dp[i][j + weights[i]] = true;
dp[i][Math.abs(j - weights[i])] = true;
}
}
}
int m = Integer.parseInt(br.readLine());
st = new StringTokenizer(br.readLine(), " ");
StringBuilder sb = new StringBuilder();
for (int i = 0; i < m; i++) {
int marble = Integer.parseInt(st.nextToken());
if (marble > 40000 || !dp[n - 1][marble]) {
sb.append('N').append(' ');
} else {
sb.append('Y').append(' ');
}
}
System.out.println(sb);
}
}
Python
import sys
n = int(sys.stdin.readline().rstrip())
weight = list(map(int, sys.stdin.readline().rstrip().split(" ")))
m = int(sys.stdin.readline().rstrip())
marble = list(map(int, sys.stdin.readline().rstrip().split(" ")))
dp = [[False for _ in range(40001)] for _ in range(n)]
result = ""
dp[0][0] = True
dp[0][weight[0]] = True
for i in range(1, n):
for j in range(40001):
if dp[i - 1][j]:
dp[i][j] = True
dp[i][j + weight[i]] = True
dp[i][abs(j - weight[i])] = True
for i in range(m):
if marble[i] > 40000 or not dp[n - 1][marble[i]]:
result += "N "
else:
result += "Y "
print(result)
Performance
'Algorithm > [Java+Python+JavaScript]BackJoon' 카테고리의 다른 글
[Java+Python]17298번, 오큰수 (0) | 2023.07.18 |
---|---|
[Java+Python]9935번, 문자열 폭발 (0) | 2023.07.17 |
[Java+Python]7579번, 앱, 냅색문제 (0) | 2023.07.16 |
[JavaScript]2941번, 크로아티아 알파벳, 좀 더 어려운 문자열 다루기 (1) | 2023.07.12 |
[Java+Python]1520번, 내리막길, DP+DFS (0) | 2023.07.12 |
[Java+Python]11049번, 행렬 곱셈 순서 (0) | 2023.07.10 |
- Total
- Today
- Yesterday
- 맛집
- 유럽여행
- a6000
- 중남미
- 유럽
- 기술면접
- 세계일주
- 스트림
- java
- Python
- spring
- RX100M5
- 알고리즘
- 여행
- Backjoon
- 자바
- 야경
- 백준
- 스프링
- 남미
- 리스트
- 지지
- 면접 준비
- Algorithm
- BOJ
- 동적계획법
- 칼이사
- 세계여행
- 파이썬
- 세모
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |