알고리즘/백준
[백준] 부분합 (1806번)
cho____sh
2020. 3. 8. 20:02
728x90
문제
10,000 이하의 자연수로 이루어진 길이 N짜리 수열이 주어진다. 이 수열에서 연속된 수들의 부분합 중에 그 합이 S 이상이 되는 것 중, 가장 짧은 것의 길이를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 N (10 ≤ N < 100,000)과 S (0 < S ≤ 100,000,000)가 주어진다. 둘째 줄에는 수열이 주어진다. 수열의 각 원소는 공백으로 구분되어져 있으며, 10,000이하의 자연수이다.
출력
첫째 줄에 구하고자 하는 최소의 길이를 출력한다. 만일 그러한 합을 만드는 것이 불가능하다면 0을 출력하면 된다.
부분합이 S가 되는 배열 p의 가능한 부분 배열의 개수를 구한다.
이 때 부분 배열은 연속적이어야한다.
이를 해결하기 위해 투 포인터라는 개념을 이용한다.
말만 투 포인터지 사실 while문 안에 변수 두 개를 이용하는 문제이다.
0번째 idx부터 N번째 idx까지 조사하는 범위를 올려가면서 합이 S보다 같거나 커지면 p[lo]를 sum에서 뺀 후 lo를 증가,
sum이 작다면 hi를 증가시키고 p[hi]를 추가하면 된다.
chosh95/STUDY
프로그래밍 문제 및 알고리즘 정리. Contribute to chosh95/STUDY development by creating an account on GitHub.
github.com
C++ 코드
#include <iostream>
#include <algorithm>
using namespace std;
int p[100001];
int N, S, res = 100001;
void partSum() {
int lo = 0, hi = 0;
int sum = p[lo];
while (lo <= hi && hi <= N){
if (sum < S) {
sum += p[++hi];
}
else if (sum == S) {
res = min(res, hi - lo + 1);
sum -= p[lo++];
}
else {
res = min(res, hi - lo + 1);
sum -= p[lo++];
}
}
}
int main()
{
cin >> N >> S;
for (int i = 0; i < N; i++) cin >> p[i];
partSum();
if (res == 100001) res = 0;
cout << res;
}
728x90