old/Algorithm

백준 1208, 부분 수열의 합

hYhY1234 2020. 5. 2. 16:54
728x90
// https://www.acmicpc.net/problem/1208
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

int main(){
    int n, s;
    cin >> n >> s;

    int half = n/2;

    vector<int> first;
    vector<int> second;
    for(int i = 0; i < half; i++){
        int temp;
        cin >> temp;
        first.push_back(temp);
    }

    for(int i = 0; i < n-half; i++){
        int temp;
        cin >> temp;
        second.push_back(temp);
    }

    vector<int> fsum;
    vector<int> ssum;

    for(int i = 0; i < (1<<half); i++){
        int temp = 0;
        for(int j = 0; j < half; j++){
            if(i&(1<<j)){
                temp += first[j];
            }
        }
        fsum.push_back(temp);
    }

    for(int i = 0; i < (1<<(n-half)); i++){
        int temp = 0;
        for(int j = 0; j < n-half; j++){
            if(i&(1<<j)){
                temp += second[j];
            }
        }
        ssum.push_back(temp);
    }

    sort(fsum.begin(), fsum.end());
    sort(ssum.begin(), ssum.end());

    int l = 0; // first 체크
    int r = ssum.size() - 1; //second 체크
    long long cc = 0; // s갯수
    while(true){
        if(l >= fsum.size() || r < 0){
            break;
        }   

        int result = fsum[l] + ssum[r];
        if(result == s){
            long long lc = 1; // first 같은거 갯수
            long long rc = 1; // second 같은거 갯수
            for(int i = l + 1; i < fsum.size(); i++){
                if(fsum[i] != fsum[l]){
                    break;
                }
                lc++;
            }

            for(int i = r - 1; i >= 0; i--){
                if(ssum[i] != ssum[r]){
                    break;
                }
                rc++;
            }

            cc += (lc * rc);
            l = l + lc;
            r = r - rc;         
        }else if(result > s){
            // cout << "큼\n";
            r--;
        }else if(result < s){
            // cout << "작음\n";
            l++;
        }

    }

    if(s == 0){
        cc = cc-1;
    }

    cout << cc << "\n";

    return 0;
}

내 코드다. 

 

1) 오류가 난 이유: 아직 long long / int 범위 판단하는데 좀 어려운게 있는거같다. 이코드에서 Long long인 부분이 사실 왜 다 long long이여야하는지 잘모르겠다. 하려면 위에 1<<half할때두 했어야하는거같은데. 근데 여튼 범위상으로 생각하면 long long이 맞기는하다. 연습하면서 정리를 해야겠다.

 

2) 범위가 40개 숫자에 대해서 부분 수열을 구하는거라 시간초과가 나온다. 그래서 20/20으로 나눈다음 구하게 해야한다 -> 다른 비슷한 문제를 풀면서 연습을 해야한다

 

3) 비트마스크를 통해서 경우의 수를 구하면 좀 빠른감이 있다. 

 

4) 알고리즘 공부는 정말 중요한 것 같다. 생각보다 클라우드나 이런 관련 지식은 하기만 하면 금방 배우는건데, 알고리즘은 시간이 오래걸리는것같다.(어렸을떄부터 시작한 친구들을 이기기 가장 힘든 분야?)