일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |
- 백준 1697
- boj 2636
- 백준 2470
- boj 10800
- boj 2178
- 10800
- 백준 2178
- boj 1697
- 2167
- boj 2470
- 백준 2108
- boj 1503
- 백준 19238
- 백준 1806
- boj 2635
- boj 2206
- 백준 2636
- boj 2167
- boj 2108
- 백준 2635
- 백준 2167
- 백준 1503
- 백준 10800
- boj 1806
- 2636
- boj 2661
- boj 2667
- 백준 2661
- 백준 2206
- boj 19238
- Today
- Total
말랑말랑한 개발자 이야기
[백준 9024번] 두 수의 합 본문
[백준 9024번] 두 수의 합
문제
여러 개의 서로 다른 정수 S = {a1, a2, …, an} 와 또 다른 정수 K 가 주어졌을 때, S 에 속하는 서로 다른 두 개의 정수의 합이 K 에 가장 가까운 두 정수를 구하시오. 예를 들어, 10 개의 정수
S = { -7, 9, 2, -4, 12, 1, 5, -3, -2, 0}
가 주어졌을 때, K = 8 에 그 합이 가장 가까운 두 정수는 {12, -4} 이다. 또한 K = 4 에 그 합이 가장 가까운 두 정수는 {-7, 12}, {9, -4}, {5, -2}, {5, 0}, {1, 2} 등의 다섯 종류가 있다.
여러 개의 서로 다른 정수가 주어졌을 때, 주어진 정수들 중에서 서로 다른 두 정수의 합이 주어진 또 다른 정수에 가장 가까운 두 정수의 조합의 수를 계산하는 프로그램을 작성하시오.
입력
프로그램은 표준입력으로 입력을 받는다. 프로그램 입력은 t 개의 테스트 케이스로 구성된다. 입력의 첫 번째 줄에 테스트 케이스의 개수를 나타내는 정수 t 가 주어진다. 두 번째 줄부터 두 줄에 한 개의 테스트 케이스에 해당하는 데이터가 주어진다. 각 테스트 케이스의 첫 번째 줄에는 두 개의 정수 n 과 K (2 ≤ n ≤ 1,000,000, -108 ≤ K ≤ 108 )가 한 개의 공백을 사이에 두고 입력된다. 두 번째 줄에는 n 개의 정수가 하나의 공백을 사이에 두고 주어지며, 각 정수의 최댓값은 108 이고, 최솟값은 -108 이다. 잘못된 데이터가 입력되는 경우는 없다.
출력
출력은 표준출력(standard output)을 사용한다. 입력되는 테스트 케이스의 순서대로 다음 줄에 이어서 각 테스트 케이스의 결과를 출력한다. 각 테스트 케이스의 출력되는 첫 줄에 입력으로 주어진 n 개의 정수들 중에서 서로 다른 두 정수의 합이 주어진 또 다른 정수 K 에 가장 가까운 두 정수의 조합의 수를 출력한다.
풀이
#include <iostream>
#include <algorithm>
#define INT_MAX 2147483647
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
int t; cin >> t;
for(int z=0;z<t;z++){
int N, K;
cin >> N >> K;
int arr[1000000] = {0,};
int cnt = 0, mini = INT_MAX;
for(int i=0;i<N;i++) cin >> arr[i];
sort(arr, arr+N);
int lp = 0, rp = N-1;
while(lp < rp){
int a = arr[lp];
int b = arr[rp];
if(K == a + b){ lp++; rp--;}
else if(K < a + b) rp--;
else lp++;
if(abs(K-(a+b)) < mini){
mini = abs(K-(a+b));
cnt = 1;
}
else if(abs(K-(a+b))==mini) cnt++;
}
cout << cnt << '\n';
}
return 0;
}
5/22일자 문제이다. 배열을 정렬한 후 양쪽에 포인터를 두고 K값에 가깝게 만들면 되는 문제이다. 전형적인 투포인터 문제였는데 실수를 알아차리지 못해서 1시간정도 걸렸다. while문의 조건이 lp < rp가 되어야하는데 처음에는 lp != rp로 풀다가 런타임에러(OutOfBounds)를 받았다. 여기에서 발생하는 문제인지 못알아차려서 오래 걸렸다.
그리고 K값에 가까운 두 정수의 갯수를 구하는 것이기 때문에 정확히 K가 안나오는 경우도 고려해야한다. 따라서 처음 생각은 a+b의 값을 모두 저장해두고 최종 값을 구할 때 살펴보는 방식이었는데 수의 범위가 커서 배열로는 불가능하고 map으로 접근했다가 이것도 안되었다. 고민을 더 하다보니 멍청한 생각이었다는 것을 깨달았다. mini라는 변수를 두고 K와 차이가 더 작은 a+b값이 나오면 mini를 갱신함과 동시에 1부터 다시 세어주면 되는 것이었다. 그래도 다행히 풀긴 풀었다.
'알고리즘 > 백준' 카테고리의 다른 글
[백준 14496번] 그대, 그머가 되어 (0) | 2021.06.18 |
---|---|
[백준 1260번] DFS와 BFS (0) | 2021.05.23 |
[백준 14430번] 자원 캐기 (0) | 2021.05.23 |
[백준 17779번] 게리맨더링2 (0) | 2021.05.18 |
[백준 5557번] 1학년 (0) | 2021.05.18 |