알고리즘 문제풀이
[백준 2003] 알고리즘 106일차 : 수들의 합 2
SiO2whocode
2021. 7. 21. 15:30
728x90
https://www.acmicpc.net/problem/2003
2003번: 수들의 합 2
첫째 줄에 N(1 ≤ N ≤ 10,000), M(1 ≤ M ≤ 300,000,000)이 주어진다. 다음 줄에는 A[1], A[2], …, A[N]이 공백으로 분리되어 주어진다. 각각의 A[x]는 30,000을 넘지 않는 자연수이다.
www.acmicpc.net
투포인터 C++
대략 25분
수열의 부분합 중 M을 만족시키는 경우의 수를 출력하는 문제이다
접근방법
투포인터를 사용해서 합이 M보다 작으면 -> end를 오른쪽으로 이동시키고
크면 -> start를 오른쪽으로 이동시킨다.
M과 같으면 경우의 수(cnt)를 1증가시키면서 end를 오른쪽으로 이동시킨다.
오답노트
구간의 합이 M보다 큰 경우 중 start와 end가 같은 점을 가리키고 있을때
그대로 start를 오른쪽으로 이동시키면 end보다 커져서 반복문을 나가게 된다.
그래서 1 2 1 과 같은 케이스에서 뒤에 1을 보지 못하고 2에서 반복문이 종료된다.
따라서 합이 M보다 클 때 start와 end가 같은 점을 가리키고 있으면 end를 오른쪽으로 이동시키고
start와 end가 다른 점을 가리키고 있으면 start를 오른쪽으로 이동시키면 된다.
이 예외는 수열 중 하나의 숫자가 M보다 클때 발생하는 예외이다.
나는 if문으로 따로 처리해줬는데 더 나은 로직이 있는지 모르겠다.
소스코드
#include <iostream>
using namespace std;
int main(){
//input
int N, target;
cin >> N >> target;
int arr[N+1];
for(int i = 0 ; i < N ; i++){
cin >> arr[i];
}
//process
int s,e;
s = e = 0;
int sum = arr[0];
int cnt = 0;
while(s <= e && e < N){
if(sum > target){
if(s == e){
sum += arr[++e];
}else{
sum -= arr[s++];
}
}else if(sum < target){
sum += arr[++e];
}else{
cnt++;
sum += arr[++e];
}
}
//output
cout << cnt << "\n";
return 0;
}
728x90