Problem Solving/Baekjoon Online Judge
[백준] 1806 부분합
jujube bat
2020. 4. 16. 15:56
✔️ 문제 링크
https://www.acmicpc.net/problem/1806
1806번: 부분합
문제 10,000 이하의 자연수로 이루어진 길이 N짜리 수열이 주어진다. 이 수열에서 연속된 수들의 부분합 중에 그 합이 S 이상이 되는 것 중, 가장 짧은 것의 길이를 구하는 프로그램을 작성하시오. 입력 첫째 줄에 N (10 ≤ N < 100,000)과 S (0 < S ≤ 100,000,000)가 주어진다. 둘째 줄에는 수열이 주어진다. 수열의 각 원소는 공백으로 구분되어져 있으며, 10,000이하의 자연수이다. 출력 첫째 줄에 구하고자 하는 최소의 길
www.acmicpc.net
✔️ 문제 이해
1. 10,000 이하의 자연수로 이루어진 길이 N짜리 수열이 있다.
2. 이 수열에서 연속된 수들의 부분합 중에 그 합이 S 이상이 되는 것 중 가장 짧은 것의 길이를 구해야한다.
3. 범위 : N (10 ≤ N < 100,000), S (0 < S ≤ 100,000,000)
✔️ 설계
1. 두 포인터를 사용한다. (S를 기준으로 구간합의 경우의 수를 생각한다.)
2. 구간합이 S이상이 될때마다, 구간 길이를 계산하고 최소값을 갱신한다.
✔️ 문제 회고
1. 두 포인터의 개념을 알고 있어서, 비교적 빨리 풀 수 있었다.
2. 문제 조건을 잘못읽어서 시간 낭비를 했다. 'S 이상' 인데 'S와 같은' 으로 착각했다.
3. 구간합 구하기 문제는 두 포인터로 쉽게 해결할 수 있다.
👨🏻💻 소스 코드
#include<iostream>
#include<algorithm>
using namespace std;
int n, s;
int arr[100000];
int res = 0x7fffffff; //최소값을 구할 것이므로 int 범위 최대값으로 초기화한다.
int main() {
cin >> n >> s;
for (int i = 0; i < n; i++) {
cin >> arr[i];
}
//시작점을 가리키는 포인터, 끝점을 가리키는 포인터, 구간 합
int start = 0, end = 0, sum = 0;
while (end <= n) {
if (sum < s) { //구간합이 s보다 작으면 end를 증가
sum += arr[end++];
}
else if (sum > s) {//구간합이 s보다 크면 start를 증가
res = min(res, end - start); //구간 길이 최소값 갱신
sum -= arr[start++];
}
else if (sum == s) {//구간합이랑 s랑 같으면 end를 증가
res = min(res, end - start); //구간 길이 최소값 갱신
sum += arr[end++];
}
}
if (res == 0x7fffffff) //조건에 맞는 구간합이 없을 경우
cout << 0;
else
cout << res;
return 0;
}