티스토리 뷰

반응형

나는 현역 취준생에서는 물러났지만, 아직 요건이 되어 참여하게 되었다. 결혼을 앞둔 32살이긴해도 .. 대학생느낌으로다가 캬캬

주관적 난이도 후기이다. 못 푼 건 좀 아쉽다. 4 솔

생각외로 시간을 많이 쓴 부분은 지문에 제약조건이 숨어있는 점이다. 코드포스에서는 제약조건 란에도 친절하게 있는데.. 카카오는 지문에 숨겨져있었다. 제약조건에 따라 문제 유형이 확확 달라지니까 ...
1번 문제 달력문제 "월의 일은 28일로", 3번 문제에서 할인율은 "10%, 20%, 30%, 40%"로 주어진다. 이 조건 때문에 코드를 수정해야하거나, 정답이 안 맞아서 굉장히 시간을 허비했다 총 합 한 50분 고생했다. 

그리고 4번 비트연산 때도 이제 머리가 굳어져서, mid = (f+t)/2 임을 찾아내지 못 해 시간을 25분 정도 썼던건 비밀.

생각외로 이번 알고리즘 느낌이 constructive 느낌인 듯 하다.

문제 주관적 난이도
1 30점 Codeforces div2. A 
2 100점 Codeforces div2. B +
3 100점 Codeforces div2. B 
4 150점 Codeforces div2. B +

1번문제 달력 ( 제약조건이 지문에 들어가있어서 약간 애매했음 )  (python) 

월마다 일자를 어떻게 처리해야할까 고민해서 relativedelta 라이브러리를 쓰려다가 custom library라 활용을 못 했다. 그것도 월은 28일로만 구성된다 라는 제약조건이 지문에 있어서, 필요가 없게 되었지만.

from datetime import datetime
from typing import Dict

def add_month(cur_date: datetime, month: int) -> datetime:
    cur_years = cur_date.year
    cur_month =  cur_date.month
    cur_day = cur_date.day
    cur_month += month
    cur_day -= 1
    if cur_day == 0:
        cur_day = 28
        cur_month -= 1
    cur_years += (cur_month-1)//12
    cur_month = ((cur_month-1)%12)+1
    return datetime(cur_years, cur_month, cur_day)

def solution(strtoday, strterms, strprivacies):
    tupled = list(map(lambda d: tuple(d.split(' ')), strterms))
    terms: Dict[str, int] = { tup[0] : int(tup[1]) for tup in tupled}

    today:datetime = datetime.strptime(strtoday, '%Y.%m.%d')

    privacies = list(map(lambda d: tuple(d.split(' ')), strprivacies))

    answer = []
    for idx, privacy in enumerate(privacies):
        strinsdate, term = privacy
        insdate = datetime.strptime(strinsdate, "%Y.%m.%d")
        expired_date = add_month(insdate, terms[term])
        if expired_date < today:
            answer.append(idx+1)

    return answer

# solution("2022.05.19", 1 , 2)
solution("2022.05.19", ["A 6", "B 12", "C 3"] , 
    ["2021.05.02 A", "2021.07.01 B", "2022.02.19 C", "2022.02.20 C"])

2번문제 ( 약간 창발적 문제 ) cpp

2번 문제 치고 좀 어려운 느낌이였다. 솔직히 문제 구조가 좀 좋았던 것 같다. 

#include <string>
#include <vector>
#include <iostream>
#include <algorithm>

using namespace std;

long long solution(int cap, int n, vector<int> deliveries, vector<int> pickups) {
    long long answer = 0;
    reverse(deliveries.begin(), deliveries.end());
    reverse(pickups.begin(), pickups.end());
    for (int i=0; i<n; i++) {
        int d = deliveries[i];
        int p = pickups[i];
        if (d || p) {
            int count = max(d,p)/cap + (max(d,p)%cap?1:0);
            answer += count*(n-i)*2;
            int dcount = d/cap + (d%cap?1:0);
            int pcount = p/cap + (p%cap?1:0);
            deliveries[i] = 0;
            pickups[i] = 0;

            int remained = (count - dcount)*cap + (d%cap?(cap-d%cap):0);
            int j = i;
            while( ++j < n && remained > 0) {
                int canDeliver = min(remained, deliveries[j]);
                if (canDeliver){
                    remained -= canDeliver;
                    deliveries[j] -= canDeliver;
                }
            }
            remained = (count - pcount)*cap + (p%cap?(cap-p%cap):0);
            j = i;
            while( ++j < n && remained > 0) {
                int canPickup = min(remained, pickups[j]);
                if (canPickup){
                    remained -= canPickup;
                    pickups[j] -= canPickup;
                }
            }
        }
        // for (int i=0; i<n; i++) {
        //     cout << deliveries[i]<< " " ;
        // }
        // cout <<"\n";
        // for (int i=0; i<n; i++) {
        //     cout << pickups[i] << " ";
        // }
        // cout <<"\n^^" << answer << "\n";
    }
    return answer;
}

int main(){
    // vector<int> input = {1,0,3,1,2};
    // vector<int> pickups = {0,3,0,4,0};
    vector<int> input = {1,0,2,0,1,0,2};
    vector<int> pickups = {0,2,0,1,0,2,0};

    // cout<< solution(4, 5, input, pickups);
    cout<< solution(2, 7, input, pickups);
}

3번문제 할인율 ( 탐색 문제 ) js

할인율이 지문에 숨겨져있어서 좀 헤맸다. 사실 지문에 숨겨져있지 않고 1~40%에서 선택하는 구조였다면 문제 구조상 각 제한시간 10초안에 풀수 있었을까? 생각이 든다.

그리고 문제에서 "10000원을 넘어가야" 라고 지문에 적혀있는데 이게 초과 개념이라 payment > userThresHold 라 작성했는데 "이상이면" (>=) 이라는 뜻이였다. 크흠 

let insdAnswer = 0;
let buyAnswer = 0;
let stateAnswer;
const visited = new Set()

function goFind(users, emoticons, state, rates) {
    const d = state.map(String).join(',')
    if(visited.has(d)) return;
    visited.add(d);

    let insdCount = 0;
    let buyPayment = 0;
    for (user of users){
        let payment = 0;
        const userLikeRate = user[0];
        const userThreadsHold = user[1];
        for (let i =0; i<emoticons.length; i++){
            if (userLikeRate > state[i] ) continue;
            const bill = emoticons[i]*(100-state[i])/100
            payment += bill;
        }
        if (payment >= userThreadsHold) {
            insdCount++;
        } 
        else buyPayment += payment;
    }

    if (insdCount > insdAnswer) {
        insdAnswer = insdCount; 
        buyAnswer = buyPayment
        stateAnswer = state;
    }

    if (insdCount == insdAnswer && buyPayment >= buyAnswer) {
        buyAnswer = buyPayment;
        stateAnswer = state;
    }

    for (let i=0; i<state.length; i++) {
        const curRate = state[i]; 
        const index = rates.findIndex(rate => rate==curRate);
        if (index == rates.length-1) continue;
        let nextIndex = index+1;
        while(true){
            if (nextIndex == rates.length ) break;
            const nextRate = rates[nextIndex];
            const nextState = [...state];
            nextState[i] = nextRate;
            goFind(users, emoticons, nextState, rates);
            if (++nextIndex == rates.length) {
                break;
            }
        }
    }
}

function solution(users, emoticons) {
  var answer = [];
  rates = [...new Set(users.map(a=>a[0]).sort((a, b)=> b-a))]
  // 모든 사용자가 구매했을 때의 가격 
  const initialState = Array(emoticons.length).fill(10)
  goFind(users, emoticons, initialState, [10, 20, 30, 40]);
  console.log(insdAnswer, buyAnswer, stateAnswer);
  return [insdAnswer, buyAnswer];
}

solution( 
    [ [40, 10000], [25, 10000], ], 
    [7000, 9000] 
);

solution( 
    [ [40, 2900], [23, 10000], [11, 5200], [5, 5900], [40, 3100], [27, 9200], [32, 6900] ], 
    [1300, 1500, 1600, 4900]
);


function test(users, emoticons, state) {
    // const users = [[40, 2900], [23, 10000], [11, 5200], [5, 5900], [40, 3100], [27, 9200], [32, 6900]] 
    // const state = [5, 11, 40 , 40];
    // const emoticons= [1300, 1500, 1600, 4900];

    let insdCount =0;
    let buyPayment = 0;
    for (user of users){
        let payment = 0;
        const userLikeRate = user[0];
        const userThreadsHold = user[1];

        for (let i =0; i<emoticons.length; i++){
            if (userLikeRate > state[i] ) continue;
            const bill = emoticons[i]*(100-state[i])/100
            payment += bill;
        }

        console.log(user, userLikeRate, userThreadsHold, payment)
        if (payment >= userThreadsHold) {
            insdCount++;
        } 
        else buyPayment += payment;
    }
    console.log(insdCount, buyPayment);
}

test(
    [ [40, 10000], [25, 10000], ], 
    [7000, 9000] ,
    [25, 40]
);


test( 
    [ [40, 2900], [23, 10000], [11, 5200], [5, 5900], [40, 3100], [27, 9200], [32, 6900] ], 
    [1300, 1500, 1600, 4900],
    [40 , 40, 20, 40]
);

4번문제  ( 이진트리 constructive algorithm 느낌) cpp

쉽다면 쉬운 문제, 2번문제보다 쉬운 느낌이였다.

#include <string>
#include <vector>
#include <iostream>
#include <algorithm>
#include <cmath>

using namespace std;

string buildTree(string str) {
    int height = 1;
    int len = str.size();
    while(true) {
        int elem = pow(2, height)-1;
        if (elem >= len) break;
        height++;
    }
    string suffix;
    int elem = pow(2, height) -1;
    for (int i=0; i<elem-len; i++) {
        suffix += "0";
    }
    string result = suffix + str;
    return result;
}

bool validCheck(string str, int f, int t) {
    int mid = (f+t)/2;
    // cout << f << " , " << t << ", " << "idx: " << mid <<"\n";
    if (f == t) return true;
    if (str[mid]=='1') {
        bool result = validCheck(str, f, mid-1);
        result &= validCheck(str, mid+1, t);
        return result;
    }

    bool result = true;
    for (int i=f; i<=t; i++) {
        result &= str[i]=='0';
    }
    return result;
}

vector<int> solution(vector<long long> numbers) {
    vector<int> answer;
    for (long long number: numbers){
        long long origin = number;
        string str;
        while(number){
            str += ('0' + (number%2));
            number /= 2;
        }
        reverse(str.begin(), str.end());
        cout << str <<"\n";
        string treeStr = buildTree(str);
        int len = treeStr.size();
        // cout << len <<"\n";
        int _answer = validCheck(treeStr, 0, len-1);
        answer.push_back(_answer);
    }

    // for (bool ans: answer) {
    //     cout << ans << " ";
    // }
    // cout <<"\n-------\n";
    return answer;
}

int main(){
    solution({7, 5});
    solution({63, 111, 95});
    solution({2, 4});
    solution({1024});
    solution({0b11111111111111111111111111111111111111111111111111111111111111});
}

 

이후로 6번 문제를 바로 풀었는데 1시간 50분 잡고 못풀었다. 5번 문제가 유니온 파인드 문제여서 잡을걸 그랬다. 지문이 길어서 허허, 바로 패스했었지만 .. 

P.S: 일단 근데 난 탈락일듯? 400점 을 못 넘겼다.

반응형