'카지no(노)'라는 단어를 본문에 쓰면 자동으로 비공개가 전환된다. velog의 검열은 이런 방식으로 하나보다.따라서 문제를 사진으로 첨부했다.
첫째 줄에 카드의 개수 N(3 ≤ N ≤ 100)과 M(10 ≤ M ≤ 300,000)이 주어진다. 둘째 줄에는 카드에 쓰여 있는 수가 주어지며, 이 값은 100,000을 넘지 않는 양의 정수이다.
합이 M을 넘지 않는 카드 3장을 찾을 수 있는 경우만 입력으로 주어진다.
첫째 줄에 M을 넘지 않으면서 M에 최대한 가까운 카드 3장의 합을 출력한다.
여기서 더 알아보고자 DFS, BFS에 대한 브루트포스와 비교하여 정리하였다.
예시: 미로 찾기 문제
예시: 지도에서 두 도시 간의 최단 거리를 구하는 문제
public class blackJack {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int count = Integer.parseInt(st.nextToken());
int maxNum = Integer.parseInt(st.nextToken());
st = new StringTokenizer(br.readLine());
List<Integer> card = new ArrayList<>();
for (int i = 0; i < count; i++) {
card.add(Integer.parseInt(st.nextToken()));
}
int result = findMaxSum(card, count, maxNum);
System.out.println(result);
}
static int findMaxSum(List<Integer> arr, int N, int M) {
int maxSum = 0;
for(int i = 0; i<N-2; i++) {
for(int j = i+1; j<N-1; j++){
for(int k = j+1; k<N; k++){
int sum = arr.get(i) + arr.get(j) + arr.get(k);
if(sum <= M){
maxSum = Math.max(maxSum, sum);
}
}
}
}
return maxSum;
}
}
if(sum <= M){
maxSum = Math.max(maxSum, sum);
}
위와 같이 코드를 짬.import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;
public class blackJack {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int count = Integer.parseInt(st.nextToken());
int maxNum = Integer.parseInt(st.nextToken());
st = new StringTokenizer(br.readLine());
int[] card = new int[count];
for (int i = 0; i < count; i++) {
card[i] = Integer.parseInt(st.nextToken());
}
int result = findMaxSum(card, count, maxNum);
System.out.println(result);
}
static int findMaxSum(int[] arr, int N, int M) {
Arrays.sort(arr); // 카드 리스트를 오름차순으로 정렬합니다.
int maxSum = 0;
for(int i = 0; i < N-2; i++) {
int j = i + 1;
int k = N - 1;
while (j < k) { // 두 번째 포인터와 세 번째 포인터가 만날 때까지 반복합니다.
int sum = arr[i] + arr[j] + arr[k];
if (sum <= M) { // 최대 숫자 합 이하인 경우에만 최대 숫자
maxSum = Math.max(maxSum, sum);
if (sum < M) { // 합이 M보다 작은 경우에는 두 번째 포인터를 오른쪽으로 이동합니다.
j++;
} else { // 합이 M보다 큰 경우에는 세 번째 포인터를 왼쪽으로 이동합니다.
k--;
}
}
}
return maxSum;
}
}
이 문제에서는 주어진 카드 리스트에서 가능한 모든 3장 조합 중에서, 최대 숫자 합이 최대 숫자 합 이하인 경우를 찾아야 합니다. 이를 구현하기 위해서는 먼저 주어진 카드 리스트를 오름차순으로 정렬하는 것이 좋습니다. 정렬된 리스트에서는 두 개의 포인터를 사용하여 가능한 모든 3장 조합을 탐색할 수 있습니다.
첫 번째 포인터는 리스트의 가장 작은 인덱스부터 시작하고, 두 번째 포인터는 첫 번째 포인터 바로 다음 인덱스부터 시작합니다. 세 번째 포인터는 리스트의 마지막 인덱스부터 시작하고, 첫 번째 포인터와 두 번째 포인터가 가리키는 카드와 함께 조합을 이룹니다.
이후에는 세 포인터가 가리키는 카드의 합을 구하고, 최대 숫자 합 이하인 경우에는 최대 숫자 합을 업데이트합니다. 그리고 두 번째 포인터와 세 번째 포인터를 각각 한 칸씩 왼쪽으로 이동시킵니다. 이를 반복하면 모든 가능한 3장 조합을 탐색할 수 있습니다.
이 알고리즘의 시간 복잡도는 O(N^2)입니다. 따라서 입력으로 큰 N값이 주어져도 빠른 실행 시간을 보장할 수 있습니다.
from itertools import combinations
m=list(map(int, input().split()))[1]
print(max((i for i in tuple(map(sum, combinations(tuple(map(int, input().split())), 3))) if i<=m)))
이 코드는 itertools 라이브러리의 combinations 함수를 사용하여 가능한 모든 3장 조합을 구하고, 이들의 합을 계산합니다. 이후에는 주어진 제한값 m 이하인 경우에 대해서만 최댓값을 찾습니다.
from itertools import combinations
itertools 라이브러리의 combinations 함수를 import 합니다.
m=list(map(int, input().split()))[1]
첫 번째 입력값은 사용하지 않으므로 무시하고, 두 번째 입력값인 최대값 m을 입력받습니다. 입력값을 공백을 기준으로 나누고, 리스트 내포(list comprehension)를 사용하여 정수형으로 변환합니다.
print(max((i for i in tuple(map(sum, combinations(tuple(map(int, input().split())), 3))) if i<=m)))
하지만 itertools 라이브러리의 함수를 이용하여 코드를 작성하였기 때문에, 직접 반복문을 작성한 경우보다 실행 시간이 더 빠를 가능성이 있습니다.라고 지피티가 말함. 이상.