2143번: 두 배열의 합
첫째 줄에 T(-1,000,000,000 ≤ T ≤ 1,000,000,000)가 주어진다. 다음 줄에는 n(1 ≤ n ≤ 1,000)이 주어지고, 그 다음 줄에 n개의 정수로 A[1], …, A[n]이 주어진다. 다음 줄에는 m(1≤m≤1,000)이 주어지고, 그 다
www.acmicpc.net
[문제 풀이]
메모제이션을 이용하여 문제를 풀었습니다.
이 문제는 입력된 A, B 배열의 연속 된 부분 배열의 합 중에 두 부분 배열의 합이 T와 같은 부분 배열의 개수를 구하는 문제였습니다.
문제의 로직은 A, B의 모든 합을 저장하여 정렬한 후 합의 경계를 찾아 경우의 수를 찾는 방식으로 구현하였습니다.
코드 설명
- A 배열에 값을 저장하고, A에서 나올 수 있는 모든 부분 합을 저장한다.
- B 배열에 값을 저장하고, B에서 나올 수 있는 모든 부분 합을 저장한다.
- A 배열의 모든 값을 반복문을 통해서 돌면서 T - A_Sum[i]의 값이 B_Sum[i]가 될 수 있는 최대, 최소 경계를 구해서 경우의 수를 계산해준다.
lower_boud, upper_bound에 대한 개념은 아래에 링크에 정리되어있습니다.
(C++ STL) lower_bound, upper_bound
lower_bound( begin(), end(), value); upper_bound( begin(), end(), value); lower_bound 란? begin()에서 end()의 범위 중에서 value값 이상이 나타는 가장 작은 이터레이터를 반환하는 것입니다. value가 존재..
steady-life.tistory.com
[코드]
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
long long T;
int N, M;
int A[1001], B[1001];
vector<int> A_Sum, B_Sum;
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
cin >> T >> N;
for (int i = 0; i < N; i++)
cin >> A[i];
int sum = 0;
for (int i = 0; i < N; i++) {
sum = A[i];
A_Sum.push_back(sum);
for (int j = i + 1; j < N; j++) {
sum += A[j];
A_Sum.push_back(sum);
}
}
cin >> M;
for (int i = 0; i < M; i++)
cin >> B[i];
for (int i = 0; i < M; i++) {
sum = B[i];
B_Sum.push_back(sum);
for (int j = i + 1; j < M; j++) {
sum += B[j];
B_Sum.push_back(sum);
}
}
sort(A_Sum.begin(), A_Sum.end());
sort(B_Sum.begin(), B_Sum.end());
long long answer = 0;
for (auto item : A_Sum) {
int temp = T - item;
auto lower = lower_bound(B_Sum.begin(), B_Sum.end(), temp);
auto upper = upper_bound(B_Sum.begin(), B_Sum.end(), temp);
answer += (upper - lower);
}
cout << answer << endl;
return 0;
}
'algorithm > BOJ' 카테고리의 다른 글
백준 10828_스택(C++) (0) | 2020.10.17 |
---|---|
백준 7453_합이 0인 네 정수(C++) (0) | 2020.10.15 |
백준 1806_부분합(C++) (0) | 2020.10.09 |
백준 2096_내려가기(C++) (0) | 2020.10.08 |
백준 1072_게임(C++) (0) | 2020.10.06 |