백준문제풀이

백준 문제 7453번 합이 0인 네 정수 문제풀이 c++

노가다 김씨 2022. 4. 10. 08:49

https://www.acmicpc.net/problem/7453

 

7453번: 합이 0인 네 정수

첫째 줄에 배열의 크기 n (1 ≤ n ≤ 4000)이 주어진다. 다음 n개 줄에는 A, B, C, D에 포함되는 정수가 공백으로 구분되어져서 주어진다. 배열에 들어있는 정수의 절댓값은 최대 228이다.

www.acmicpc.net

 

문제해석

전에 풀어봤던 3151번 합이 0 문제와 비슷한 문제 같다는 느낌을 받았다. https://www.acmicpc.net/problem/3151

다만 3151번은 3개 합이 0이 되는 쌍의 갯수를 찾는 것 이고 이 문제는 4개 합이 0이 되는 쌍의 갯수를 찾는 것 이다.

 

그냥 모든 경우를 확인해버리면 배열의 크기가 최대 4000개 이므로 4000^4 이므로 이렇게 풀면 시간초과가 난다.

 

그렇다면 두 쌍씩 묶어서 생각해보자 

첫번째 그룹을 A배열과 B배열의 쌍 최대 4000^2=16000000가지

두번째 그룹을 C배열과 D배열의 쌍 최대 4000^2=16000000가지

 

그리고 두번째 그룹을 정렬 후 첫번째 그룹의 원소의 -1을 곱한것들을 차례로 두번째 그룹에서 이분탐색을 해본다.

만약 존재한다면 그 A B C D는 합이 0이 되는 4개의 쌍이 된다.

 

이렇게 하면 O(n^2+n^2+n^2logn^2)=O(n^2logn^2)의 시간복잡도를 가지므로 문제를 시간 안에 해결 할 수있다.

 

 

 

코드

#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
typedef long long int ll;
using namespace std;
vector <ll> v;
vector <ll> u;
ll A[4000];
ll B[4000];
ll C[4000];
ll D[4000];
int main(){
    cout.tie(NULL);
    cin.tie(NULL);
    ios_base::sync_with_stdio(false);
    ll n; cin>>n;
    ll sum=0;
    for(ll i=0; i<n; i++)
    {
        cin>>A[i]>>B[i]>>C[i]>>D[i];
    }
    for(int i=0; i<n; i++)
    {
        for(int j=0; j<n; j++)
        {
            v.push_back(A[i]+B[j]);
            u.push_back(C[i]+D[j]);
        }
    }
    sort(u.begin(),u.end());
    for(int i=0; i<v.size(); i++)
    {
        ll x=upper_bound(u.begin(),u.end(),-v[i])-u.begin();
        ll y=lower_bound(u.begin(),u.end(),-v[i])-u.begin();
        if(u[y]==-v[i])
        {
            sum=sum+x-y;
        }
    }
    cout<<sum<<"\n";
}

 

원래 처음엔 이분 탐색과 외에 맵을 사용하여 푸는것도 고려를 해보았는데 메모리 초과가 날 것 같아서 이분탐색 코드를 제출 한 후에 맵사용한 코드역시 제출해보았는데 예상대로 메모리 초과가 났다.