백준 1074 - Z

문제 링크

생각 및 접근

  • 전형적인 분할 정복 문제다.
  • 그런데, 시간 제한이 있으므로 시간을 고려해야 한다.

첫 접근

  • 분할 정복을 재귀로 구현해 표를 네 부분으로 나눠서 Z 방향으로 순회하였다.
  • 첫 접근으로 cnt 변수를 선언해서 표의 모든 원소를 돌면서 하나씩 늘려가다가, 목표 지점에 도달하면 cnt를 출력하고 끝내려했다.
  • 하지만, 시간 초과가 발생했다.

개선

  • 네 부분으로 나눠서 탐색할 때, 각 부분에 목표 지점이 없다면, 부분의 원소 갯수만큼 cnt를 늘려주고 그냥 넘어가면 된다. 목표 지점만 탐색하면 된다.

코드

#include <bits/stdc++.h>
using namespace std;

int cnt, N, r, c;

void dc(int size, int x, int y){
    if(size == 1){
        if(x == r && y == c){
            cout << cnt;
            exit(0);
        }
        cnt++;
    }
    else{
        if(x <= r && r <= x + size / 2 && y <= c && c <= y + size / 2)
            dc(size / 2, x, y);
        else
            cnt += pow((size / 2), 2);

        if(x <= r && r <= x + size / 2 && y + (size / 2) <= c && c <= y + size)
            dc(size / 2, x, y + (size / 2));
        else
            cnt += pow((size / 2), 2);

        if(x + (size / 2) <= r && r <= x + size && y <= c && c <= y + size / 2)
            dc(size / 2, x + (size / 2), y);
        else
            cnt += pow((size / 2), 2);

        if(x + (size / 2) <= r && r <= x + size && y + (size / 2) <= c && c <= y + size)
            dc(size / 2, x + (size / 2), y + (size / 2));
        else
            cnt += pow((size / 2), 2);
    }
}

int main(){
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);    cout.tie(NULL);

    cin >> N >> r >> c;
    dc(pow(2, N), 0, 0);
}

채점 결과

'Coding Test > acmicpc' 카테고리의 다른 글

백준 14502 - 연구소 (c++)  (0) 2020.08.07
백준 1759 - 암호 만들기 (c++)  (0) 2020.08.05
백준 14501 - 퇴사 (c++)  (0) 2020.08.05
백준 1339 - 단어 수학 (c++)  (0) 2020.08.04
백준 1748 - 수 이어 쓰기 1 (c++)  (0) 2020.08.03

백준 14501 - 퇴사

문제 링크

생각 및 접근

  • 동적 프로그래밍을 통해 n번 날짜에서 가질수 있는 최대 금액을 기록 하려고 했다.

  • 상담 일정표에서 맨 앞에 것 부터 탐색한다.

    • 상담이 끝났을 때의 날짜 이후는 그 상담의 보상을 받을 수 있는 날짜들이다. 그러므로, 그 상담이 시작되는 날까지 받을 수 있는 보상 + 그 상담의 보상 이 큰지, 그 상담이 없어도 기존에 가질 수 있는 보상이 더 큰지 비교하면 된다.

        for(int i = 1; i <= n; i++){
            int day = d[i] + i;
            int pay = p[i] + dp[i];
      
            for(int j = day; j <= n + 1; j++){
                dp[j] = max(dp[j], pay);
            }
        }

코드

#include <bits/stdc++.h>
using namespace std;

int n, a, b, d[16], p[16], dp[16];

int main(){
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);    cout.tie(NULL);

    cin >> n;
    for(int i = 1; i <= n; i++){
        cin >> a >> b;
        d[i] = a;
        p[i] = b;
    }

    for(int i = 1; i <= n; i++){
        int day = d[i] + i;
        int pay = p[i] + dp[i];

        for(int j = day; j <= n + 1; j++){
            dp[j] = max(dp[j], pay);
        }
    }

    cout << dp[n + 1];
}

채점 결과

'Coding Test > acmicpc' 카테고리의 다른 글

백준 1759 - 암호 만들기 (c++)  (0) 2020.08.05
백준 1074 - Z (c++)  (0) 2020.08.05
백준 1339 - 단어 수학 (c++)  (0) 2020.08.04
백준 1748 - 수 이어 쓰기 1 (c++)  (0) 2020.08.03
백준 6064 - 카잉 달력 (c++)  (0) 2020.08.03

백준 1339 - 단어 수학

문제 링크

접근 및 생각

잘못된 접근

  • 처음에 들어온 문자열을 문자로 쪼개서 문자들을 sort해서 next_permutation을 돌렸다. 돌리면서 한 문자에 어떤 숫자가 들어가는 지 결정하고, 또 문자열을 쪼개서 다 합한 것을 계산했다. 뭐라 설명해야할 지 모르겠고, 그냥 미친 짓이였다.

올바른 접근

  • 받은 스트링이 ABCDE가 있다면, 이를 10000 * A + 1000 * B + 100 * C + 10 * D + 1 * E처럼 해석 하는 것이다.
    • 나는 map<char, int> m을 선언해서 char에는 문자를, int에는 숫자를 넣어줬다.
  • map에 다 넣은 뒤, map의 int 기준으로 내림차순 정렬을 하려고 했다. 그래서 새 구조체를 선언했고, map을 vector로 변환하는 과정을 거쳤다.
      // 구조체
      struct Le{
          char letter;
          int value;
          Le(char a, int b){
              letter = a;
              value = b;
          }
          bool operator < (const Le & b) const {
              return value > b.value;
          }
      };
      // 벡터로 변환하는 과정
      for(auto & i : m){
          if(i.second != 0){
              exist.push_back(Le(i.first, i.second));
          }
      }
  • 내림차순 정렬을 하고, 정렬한 원소 순서대로 9, 8, 7, ...을 넣어서 계산해주면 된다.
      int cnt = 9;
      sort(exist.begin(), exist.end());
      for(auto i : exist){
          answer += (cnt * i.value);
          cnt--;
      }

코드

#include <bits/stdc++.h>
using namespace std;

struct Le{
    char letter;
    int value;
    Le(char a, int b){
        letter = a;
        value = b;
    }
    bool operator < (const Le & b) const {
        return value > b.value;
    }
};

int n, answer;
string temp;
map<char, int> m;
vector<Le> exist;

int main(){
    ios_base::sync_with_stdio(false);

    cin >> n;
    for(int i = 1; i <= n; i++){
        cin >> temp;
        for(int i = 0; i < temp.length(); i++){
            m[temp[i]] += pow(10, temp.length() - i - 1);
        }
    }

    for(auto & i : m){
        if(i.second != 0){
            exist.push_back(Le(i.first, i.second));
        }
    }

    int cnt = 9;
    sort(exist.begin(), exist.end());
    for(auto i : exist){
        answer += (cnt * i.value);
        cnt--;
    }

    cout << answer;
}

채점 결과

'Coding Test > acmicpc' 카테고리의 다른 글

백준 1074 - Z (c++)  (0) 2020.08.05
백준 14501 - 퇴사 (c++)  (0) 2020.08.05
백준 1748 - 수 이어 쓰기 1 (c++)  (0) 2020.08.03
백준 6064 - 카잉 달력 (c++)  (0) 2020.08.03
백준 1107 - 리모컨 (c++)  (0) 2020.08.02

백준 1748 - 수 이어 쓰기 1

문제 링크

생각 및 접근

  • n으로부터 자릿수를 먼저 구했다.
      answer = n;
      while(answer != 0){
          answer /= 10;
          cnt++;
      }
  • 1의 자릿수부터 n의 자릿수 까지 만들 새 수의 길이를 차례차례 구한다.
    • i != cnt
      • (99 - 10 + 1) * 2
      • (999 - 100 + 1) * 3
      • (9999 - 1000 + 1) * 4
      • ...
      • (10 ^ k - 10 ^ (k - 1)) * k
    • i == cnt
      • (n - 10 ^ (cnt - 1) + 1) * cnt

코드

#include <bits/stdc++.h>
using namespace std;

int n, answer, cnt;

int main(){
    ios_base::sync_with_stdio(false);
    cin >> n;

    answer = n;
    while(answer != 0){
        answer /= 10;
        cnt++;
    }

    for(int i = 1; i <= cnt; i++){
        if(i == cnt)    answer += (n - pow(10, i - 1) + 1) * i;
        else            answer += (pow(10, i) - pow(10, i - 1)) * i;
    }

    cout << answer;
}

채점 결과

'Coding Test > acmicpc' 카테고리의 다른 글

백준 1074 - Z (c++)  (0) 2020.08.05
백준 14501 - 퇴사 (c++)  (0) 2020.08.05
백준 1339 - 단어 수학 (c++)  (0) 2020.08.04
백준 6064 - 카잉 달력 (c++)  (0) 2020.08.03
백준 1107 - 리모컨 (c++)  (0) 2020.08.02

백준 6064 - 카잉 달력

문제 링크

생각과 접근

처음 생각

  • 처음 문제에 접근할 때 단순히 문제의 조건대로 1년씩 늘려서 x와 y를 늘려주는 식으로 했다. 역시나 시간 초과. 결국 띄엄띄엄 검사하는 생각해야 했다.

개선한 생각

  • 문제의 조건에 의해 <1, 1>이 <m, n>이 되면 카잉 달력은 끝나게 된다. 그렇다면 <m, n>이 되려면 몇 년이 지나야 할까. 결론부터 말하면 m과 n의 최소공배수가 되면 끝난다 . 그 이유는 왼쪽 수가 m이 되는 경우는 카잉년이 m의 배수가 될 때이고, 오른쪽 수가 n이 되는 경우는 카잉년이 n의 배수가 될 때이기 때문이다. 그래서, limit이라는 변수를 선언해서 카잉년을 몇 년까지 검사를 해야할 지 담아 놓았다. 최소공배수를 구하기 위해, 간단히 함수도 구현해 주었다.

      int gcd(int a, int b){
          while(b != 0){
              int r = a % b;
              a = b;
              b = r;
          }
          return a;
      }
    
      int lcm(int a, int b){
          return a * b / gcd(a, b);
      }
  • 문제에서 요구하는 것은 _<x, y>는 몇 년째인가?_ 이다. 위와 같이 배수적인 표현으로 생각해보면, 왼쪽 좌표는 카잉년에서 m으로 나눈 나머지 가 되고, 오른쪽 좌표는 카이년에서 n으로 나눈 나머지 가 된다. 숫자를 하나씩 늘려가면서 생각해보면 쉽게 나오는 결론이였다.

    • 현재 카잉년을 tar이라고 했을 때,

      • tar % m = x이고
      • tar % n = y
        tar는 <x, y>의 카잉년이 된다.
        만일 찾은 카잉년이 limit 이상으로 넘어가게 된다면, 답이 될 수 없다.
    • 위의 조건으로 코드를 구현해보았다.

        cin >> m >> n >> x >> y;
      
        flag = 0;
        limit = lcm(m, n);
      
        for(int j = x; j <= limit ; j += m){
            if(j % n == y % n){
                flag = 1;
                cout << j << endl;
                break;
            }
        }
        if(flag == 0){
            cout << "-1" << endl;
        }
      • for문에서 나타나는 j가 위에서 설명한 tar이 된다. j는 for문을 돌면서 왼쪽 좌표가 x가 되는 케이스 를 찾는다. 그 j에서 오른쪽 좌표가 y가 되는 케이스 를 찾으면 그 값이 출력해야 하는 값이 된다.

코드

#include <bits/stdc++.h>
using namespace std;

int gcd(int a, int b){
    while(b != 0){
        int r = a % b;
        a = b;
        b = r;
    }
    return a;
}

int lcm(int a, int b){
    return a * b / gcd(a, b);
}

int sit, m, n, x, y, limit, flag;

int main(){
    ios_base::sync_with_stdio(false);

    cin >> sit;
    for(int i = 1; i <= sit; i++){
        cin >> m >> n >> x >> y;

        flag = 0;
        limit = lcm(m, n);

        for(int j = x; j <= limit ; j += m){
            if(j % n == y % n){
                flag = 1;
                cout << j << endl;
                break;
            }
        }
        if(flag == 0){
            cout << "-1" << endl;
        }
    }
}

채점 결과

'Coding Test > acmicpc' 카테고리의 다른 글

백준 1074 - Z (c++)  (0) 2020.08.05
백준 14501 - 퇴사 (c++)  (0) 2020.08.05
백준 1339 - 단어 수학 (c++)  (0) 2020.08.04
백준 1748 - 수 이어 쓰기 1 (c++)  (0) 2020.08.03
백준 1107 - 리모컨 (c++)  (0) 2020.08.02

백준 1107 - 리모컨

문제 링크

생각과 접근

  • 리모콘은 같은 숫자를 여러 번 누를 수 있는, 중복순열의 형태이다. 중복순열을 구현할 수 있다면 쉽게 풀 수 있는 문제였다.
  • 고장난 리모콘 버튼을 통해서 살아있는 리모콘 숫자를 기억하는 vector<int> live;를 선언했다.
  • 우선, answer의 초깃값을 answer = abs(target - START);로 잡아두었다. 단순히 +와 - 키로 얻을 수 있는 리모콘 클릭 수로 초기화한 것이다.
  • 채널의 범위가 0 <= N <= 500000이므로, 1개부터 6개까지 고를 수 있는 중복순열을 구현해 기존의 answer와 비교해서, 더 작은 값으로 update하면 되겠다.
      void dfs(int cnt, int tar){
          if(cnt == tar){
              temp = 0;
              for(int i = 0; i < cnt; i++){
                  temp *= 10;
                  temp += cand[i];
              }
              answer = min(answer, tar + abs(target - temp));
          }
          else{
              // 중복순열을 하는 코드
              // vector live를 전부 돌면서 그냥 넣으면 된다. 왜? 버튼을 누르는 수는 제한이 없으니까!
              for(int i = 0; i < live.size(); i++){
                  cand[cnt] = live[i];
                  dfs(cnt + 1, tar);
              }
          }
      }

코드

#include <bits/stdc++.h>
#define START 100
using namespace std;

int target, brokenNum, temp, answer;
vector<int> tmp(10, 0);
vector<int> live;
vector<int> cand(6, 0);

void dfs(int cnt, int tar){
    if(cnt == tar){
        temp = 0;
        for(int i = 0; i < cnt; i++){
            temp *= 10;
            temp += cand[i];
        }
        answer = min(answer, tar + abs(target - temp));
    }
    else{
        for(int i = 0; i < live.size(); i++){
            cand[cnt] = live[i];
            dfs(cnt + 1, tar);
        }
    }
}

int main(){
    ios_base::sync_with_stdio(false);

    cin >> target >> brokenNum;
    for(int i = 0; i < brokenNum; i++){
        cin >> temp;
        tmp[temp] = 1;
    }
    for(int i = 0; i <= 9; i++){
        if(tmp[i] == 0)
            live.push_back(i);
    }

    answer = abs(target - START);

    for(int i = 1; i <= 6; i++){
        for(int j = 0; j < 6; j++){
            cand[j] = 0;
        }
        dfs(0, i);
    }

    cout << answer;
}

채점 결과

'Coding Test > acmicpc' 카테고리의 다른 글

백준 1074 - Z (c++)  (0) 2020.08.05
백준 14501 - 퇴사 (c++)  (0) 2020.08.05
백준 1339 - 단어 수학 (c++)  (0) 2020.08.04
백준 1748 - 수 이어 쓰기 1 (c++)  (0) 2020.08.03
백준 6064 - 카잉 달력 (c++)  (0) 2020.08.03

200801 toss 토스 server 코딩 테스트 후기

server-1 : coding test

  • 단순 코딩테스트 문항이였다. 필자는 C++로 풀었다.
  • server 분야라서 모든 언어가 사용 가능했지만, 백준이나 프로그래머스에 있는 문제처럼 문제가 친절하지는 않았다. 예로 들어, 숫자가 주어질 때 -1을 입력하면 입력을 그만두게 하는 문제들이 백준에는 있지만, 토스 코테에는 그러한 문항이 존재하지 않아 모든 input을 string으로 받아 데이터를 내 입맛대로 분류를 해야해서 매우 불편했다. string을 잘 다루는 것을 코테의 목적이 투영되는 것으로 보아 머지 않은 미래에 모든 코테의 언어는 python으로 바뀔지 모른다.
  • 비교적 쉬운 문제(카카오 코테로 치면 1번이나 2번 문제들)들을 얼마나 빨리 푸는 가를 코테의 목적을 둔 것 같았다.
  • 코테가 시작되었을 때 긴장된 탓인지 손이 떨려 오타가 많이 났고, 원래 쓰던 함수도 잘 생각나지 않았다. 다음 코테에서는 마인드 컨트롤을 하고 코테를 보아야 겠다.

server-2 : background investigation

  • CS 지식을 묻는 문제였다.
  • 필자의 전공은 컴공이지만, 4년간 대학을 다니면서 모든 지식을 까먹은 것 같았고, 나중에 기술 면접이나 이러한 investigation을 치룰 때 CS 지식이 필요할 것으로 보여 조만간 스터디를 등록해야겠다고 마음 먹었다.

총평

  • 아직 나는 너무 부족하다.
  • 유쾌한 반란을 시작해보겠다.

프로그래머스 42628 - 이중우선순위큐

문제 링크

생각 및 접근

  • 이중우선순위큐라고 해서 우선순위 큐를 활용해야 될 것 같았지만, 문제를 분석하다 보니 그냥 vector로 풀어도 상관없겠다는 판단이 났다.
  • operations 돌리기
    • I 숫자라면 vector에 삽입
    • D 1이라면 내림차순으로 나열해서 pop_back()
    • D -1이라면 오름차순으로 나열해서 pop_back()

코드

#include <bits/stdc++.h>
using namespace std;

vector<int> solution(vector<string> operations) {
    vector<int> q;
    for(auto o : operations){
        if(o[0] == 'I'){
            string temp = o.substr(2);
            q.push_back(stoi(temp));
        }
        else if(!q.empty() && o == "D 1"){
            if(q.size() != 1)    sort(q.begin(), q.end());
            q.pop_back();
        }
        else if(!q.empty() && o == "D -1"){
            if(q.size() != 1)    sort(q.rbegin(), q.rend());
            q.pop_back();
        }
    }

    sort(q.begin(), q.end());
    vector<int> answer;
    if(q.empty()){
        answer.push_back(0);
        answer.push_back(0);
    }
    else{
        answer.push_back(q[q.size() - 1]);
        answer.push_back(q[0]);
    }
    return answer;
}

채점 결과

+ Recent posts