어흥

[백준 9007] 카누 선수 (C++) 본문

알고리즘/백준

[백준 9007] 카누 선수 (C++)

라이언납시오 2022. 1. 12. 19:09
728x90
반응형

문제 링크: https://www.acmicpc.net/problem/9007

 

9007번: 카누 선수

이 문제에서는 입력은 표준 입력을 사용한다. 입력의 첫 줄에는 T개의 테스트 케이스가 주어진다. 각 테스트 케이스에는 두 개의 정수 k와 n이 주어지며, k( 1 ≤ k ≤ 40,000,000)는 보트의 특정 값 그

www.acmicpc.net

1. 주의할 점

- 시간복잡도를 줄이려고 노력한다

- TestCase를 시작하기 전, 연산에 사용되는 모든 벡터 및 값을 초기화한다

 

2. 구현

- 4개의 집합(V[])을 2개씩 묶어서 각 집합의 모든 원소의 합을 twoSum[]에 저장한다

- 두 집합의 합을 구할때: O(N^2)

- twoSum을 통해 Weight과 비교할 때(twoSum[0]의 길이를 A(=N^2)라고 할 때): O(AlgA)

- 이분탐색을 이용해서 해결한다

- twoSum[] 배열중에서 1개의 배열만 오름차순으로 정렬한다(시간복잡도: O(AlgA))

- Result의 값을 각 배열 첫번째 원소의 합으로 초기화한다

- twoSum[0]의 모든 원소에 대해 twoSum[1]의 원소와 비교를 한다. 이때, 이분탐색을 통해 twoSum[1]을 탐색할 때의 시간복잡도를 A에서 lgA로 줄인다

- 각 조건에 맞게 Result를 갱신하며, L과 R의 값을 수정한다

#include <iostream>
#include <set>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
    ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
    int test,weight,num,val;
    cin >> test;
    while(test--){
        cin>>weight>>num;
        vector<int> v[4];
        for(int i=0;i<4;i++){
            for(int j=0;j<num;j++){
                cin>>val;
                v[i].push_back(val);
            }
        }
        vector<int> twoSum[2];
        for(int i=0;i<2;i++)
            for(int j=0;j<num;j++)
                for(int k=0;k<num;k++)
                    twoSum[i].push_back(v[i*2][j]+v[i*2+1][k]);
        sort(twoSum[1].begin(),twoSum[1].end());
        
        int result = twoSum[0][0]+twoSum[1][0];
        bool finish = false;
        for(int i=0;i<num*num;i++){
            int l=0,r=num*num-1,mid,firVal = twoSum[0][i];
            while(l<=r){
                mid = l +(r-l)/2;
                int sum = firVal+twoSum[1][mid];
                if(abs(result-weight)>abs(weight-sum))   result = sum;
                else if(abs(result-weight)==abs(weight-sum)) result = min(result,sum);
                if(sum<weight)  l = mid+1;    //sum을 늘린다
                else if(sum>weight) r = mid-1;        //sum을 줄인다
                else{       //정확히 sum
                    finish=true;
                    break;
                }
            }
            if(finish) break;
        }
        cout<<result<<'\n';
    }
    return 0;
}
728x90
반응형

'알고리즘 > 백준' 카테고리의 다른 글

[백준 15997] 승부 예측 (C++)  (0) 2022.01.21
[백준 2026] 소풍 (C++, Java)  (0) 2022.01.16
[백준 3107] IPv6 (C++, Java)  (0) 2022.01.04
[백준 2064] IP 주소 (C++)  (0) 2021.12.29
[백준 14940] 쉬운 최단거리 (C++)  (0) 2021.12.26
Comments