일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- 최장길이바이토닉수열
- 백준 1464
- 2493 백준
- 비트마스킹
- bfs
- 백준 뒤집기 3
- 1939백준
- disjoint set
- 그래프 탐색
- 패스트캠퍼스
- 이분 탐색
- 그래프이론
- 이분탐색
- 결정문제
- 구현
- boj 1464
- union find
- 그래프 이론
- 분할정복
- 최장증가수열
- parametric search
- 그래프탐색
- 뒤집기 3
- 서로소 집합
- 브루트포스
- 재귀
- 결정 문제
- Lis
- 깊이 우선 탐색
- DP
Archives
- Today
- Total
알고리즘 문제풀이
[BOJ] 1806 번 - 부분합 본문
백준 1806번 - 부분합
시간제한 | 메모리 제한 | 제출 | 정답 | 맞은 사람 | 정답 비율 |
---|---|---|---|---|---|
1 초 | 128 MB | 21371 | 5642 | 3964 | 25.503% |
문제
10,000 이하의 자연수로 이루어진 길이 N짜리 수열이 주어진다. 이 수열에서 연속된 수들의 부분합 중에 그 합이 S 이상이 되는 것 중, 가장 짧은 것의 길이를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 N (10 ≤ N < 100,000)과 S (0 < S ≤ 100,000,000)가 주어진다. 둘째 줄에는 수열이 주어진다. 수열의 각 원소는 공백으로 구분되어져 있으며, 10,000이하의 자연수이다.
출력
첫째 줄에 구하고자 하는 최소의 길이를 출력한다. 만일 그러한 합을 만드는 것이 불가능하다면 0을 출력하면 된다.
예제 입력 1
10 15
5 1 3 5 10 7 4 9 2 8
예제 출력 1
2
출처
www.acmicpc.net/problem/1806
1806번: 부분합
첫째 줄에 N (10 ≤ N < 100,000)과 S (0 < S ≤ 100,000,000)가 주어진다. 둘째 줄에는 수열이 주어진다. 수열의 각 원소는 공백으로 구분되어져 있으며, 10,000이하의 자연수이다.
www.acmicpc.net
알고리즘 분류
- 투 포인터
접근 방법
투 포인터 기법을 활용하는 문제였다.
left를 부분합 중에 합이 S이상이 되는 것 중 가장 짧은 것의 길이를 가지는 구간의 왼쪽, right를 구간의 오른쪽이라 하자.
그리고 left와 right는 0에서 부터 시작한다고 가정하자.
정렬된 배열 arr에 대해 [left, right]까지의 합이 S이상 이면, 정답 후보에 넣고 구간의 길이를 최대한 줄이기 위해 left를 증가시켜준다.
반대로, [left,right]까지의 합이 S미만이면, 구간의 길이를 늘려보기 위해 right를 증가시켜준다.
다음과 같은 방법으로 최적해를 구할 수 있다.
소스 코드
#include <bits/stdc++.h>
using namespace std;
vector<int> ac_sum;
int get_sum(int left, int right){
if( left == 0 ){
return ac_sum[right];
}
return ac_sum[right] - ac_sum[left-1];
}
int main(void){
ios_base::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int N, S;
cin >> N >> S;
vector<pair<int,int>> v;
ac_sum.resize(N,0);
vector<int> arr(N);
int sum = 0;
for(int i=0; i<N; i++){
cin >> arr[i];
sum += arr[i];
ac_sum[i] = sum;
}
sort(arr.begin(), arr.end());
int left, right;
left = right = 0;
while( 0 <= left && left < N && 0 <= right && right < N ){
int sum = get_sum(left, right);
if( sum >= S )
v.push_back({left, right});
if( sum < S ){
right += 1;
}
else{
left += 1;
}
}
if( v.empty() )
cout << 0;
else{
int min_len = 1e9;
for( auto it : v ){
int len = it.second - it.first + 1 ;
if( min_len > len )
min_len = len;
}
cout << min_len;
}
return 0;
}
'자료구조 + 알고리즘 > [BOJ]' 카테고리의 다른 글
[BOJ] 1439번 - 뒤집기 (0) | 2020.12.28 |
---|---|
[BOJ] 9466번 - 텀 프로젝트 (0) | 2020.12.27 |
[BOJ] 2470번 - 두 용액 (0) | 2020.12.26 |
[BOJ] 12100번 - 2048(Easy) (0) | 2020.12.18 |
[BOJ] 10429번 - QUENTO (0) | 2020.12.17 |
Comments