1. Day04

  • Blueprint 라이브 세션 및 과제
  • 개인 공부

2. 라이브 세션

  • 블루프린트 학습
    • 블루프린트로 캐릭터 세팅
    • Enhanced Input System
    • 캐릭터 이동 구현
    • 캐릭터 위 아래 카메라 각도 제한(Camera Manager → Set View Pitch Max & Min)
  • 과제(레벨 디자인 스케치)
    • 간단한 점프맵과 상호작용 및 함정

3. 개인공부

  • C++ 코딩테스트 완전정복 강의 (2-3, 2-4)
    • 숫자 다루기(반올림, 올림, 소수점 버리기/내림)
    • 문자열 스트림(공백 기준으로 분리, 특정 문자 기준으로 분리, 진법 변환)
  • 실버2 2630번 색종이만들기(정복 분할)
    • 처음에 분할 정복에 대한 접근 방법이 어려워 접근 방식만 따로 힌트를 얻음(클로드 사용)
solve(x, y, size):
    if 영역 (x, y)부터 size×size가 모두 같은 색:
        해당 색 카운트 증가
        return

    half = size / 2
    solve(x, y, half)              // 1사분면
    solve(x, y + half, half)       // 2사분면  
    solve(x + half, y, half)       // 3사분면
    solve(x + half, y + half, half) // 4사분면
  • 처음에 vector<vector> V 를 전역 변수로 선언한다음 크기를 지정안한 상태로 V[i][j]로 접근하여 오류가 발생함 → main()함수 안에서 V.resize(N + 1, vector(N + 1))로 해결
// 실버2 2630번 색종이만들기(정복 분할)
#include <iostream>
#include <vector>

using namespace std;

// solve() 함수에 사용하기 위해 전역 선언
vector<vector<int>> V;
int countW = 0;
int countB = 0;

// (x, y) 위치부터 size * size 크기의 영역을 처리하는 재귀 함수
void solve(int x, int y, int size)
{    
    // 현재 영역의 파란색 하얀색 칸 개수 세기
    int B = 0;
    int W = 0;

    for (int i = x; i < x + size; i++)
    {
        for (int j = y; j < y + size; j++)
        {
            if (V[i][j] == 1)
            {
                B++;
            }
            else
            {
                W++;
            }
        }
    }

    // 전체가 한 색이면 카운트하고 종료
    if (B == size * size)
    {
        countB++;
        return;
    }
    else if (W == size * size)
    {
        countW++;
        return;
    }

    // 분할: 4등분해서 각각 재귀 호출
    int half = size / 2;
    solve(x, y, half);
    solve(x, y + half, half);
    solve(x + half, y, half);
    solve(x + half, y + half, half);
}

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

    int N;
    cin >> N;

    // V[0][0]을 피하고 (1,1)부터 (N,N)까지 사용하기 위해서 N + 1
    V.resize(N + 1, vector<int>(N + 1));

    for (int i = 1; i <= N; i++)
    {
        for (int j = 1; j <= N; j++)
        {
            cin >> V[i][j];
        }
    }

    solve(1, 1, N);

    cout << countW << '\n' << countB << '\n';
    return 0;
}

// solve()함수 조기 종료를 이용한 효율성 개선버전
void solve(int x, int y, int size)
{
    int first = V[x][y];  // 첫 칸의 색 저장

    // 모든 칸이 같은 색인지 확인 (다르면 즉시 분할)
    for (int i = x; i < x + size; i++)
    {
        for (int j = y; j < y + size; j++)
        {
            if (V[i][j] != first)  // 다른 색이 발견되는 순간 4등분하여 재귀함수 호출 후 종료
            {
                // 4등분하여 재귀
                int half = size / 2;
                solve(x, y, half);
                solve(x, y + half, half);
                solve(x + half, y, half);
                solve(x + half, y + half, half);
                return;
            }
        }
    }

    // 여기 도달하면 모두 같은 색
    if (first == 1)
        countB++;
    else
        countW++;
}
  • 실버2 2805번 나무 자르기(이분 탐색)
    • 어제 이후 이분 탐색 문제의 적응을 위해 한 문제 더 풀이
      • 처음에는 얻은 나무의 길이가 M보다 작은데도 정답을 갱신해서 문제가 생겼으나 갱신을 하지않도록 수정
// 실버2 2805번 나무 자르기(이분 탐색)
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

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

    long long N, M;
    cin >> N >> M;

    vector<long long> v(N);
    long long answer = 0;
    long long left = 1;
    long long right = 0;
    long long mid;

    for (int i = 0; i < N; i++)
    {
        cin >> v[i];
        right = max(right, v[i]);
    }

    // 이분 탐색: 절단기 높이의 최대값 찾기
    while (left <= right)
    {
        mid = (left + right) / 2;

        // mid 높이로 잘랐을 때 얻는 나무 총량 계산
        long long result = 0;
        for (int i = 0; i < N; i++)
        {
            // 음수가 더해지지 않도록
            if (v[i] > mid)
            {
                result += (v[i] - mid);
            }
        }

        // 나무 길이 부족 -> 높이를 낮춰야 함
        if (result < M)
        {
            right = mid - 1;
        }
        // 나무 길이 충분 -> 높이 더 올릴 수 있음
        else
        {
            answer = max(answer, mid);
            left = mid + 1;
        }
    }

    cout << answer << '\n';

    return 0;
}
  • 실버2 2805번 나무 자르기(개선 버전)
    • answer에 굳이 최대길이를 저장하지 않아도 마지막에 남는 right값이 정답
// 실버2 2805번 나무 자르기(이분 탐색)
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

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

    long long N, M;
    cin >> N >> M;

    vector<long long> v(N);
    long long left = 1;
    long long right = 0;


    for (int i = 0; i < N; i++)
    {
        cin >> v[i];
        right = max(right, v[i]);
    }

    // 이분 탐색: 절단기 높이의 최대값 찾기
    while (left <= right)
    {
        long long mid = (left + right) / 2;

        // mid 높이로 잘랐을 때 얻는 나무 총량 계산
        long long result = 0;
        for (int i = 0; i < N; i++)
        {
            // 음수가 더해지지 않도록
            if (v[i] > mid)
            {
                result += (v[i] - mid);
            }
        }

        // 나무 길이 부족 -> 높이를 낮춰야 함
        if (result < M)
        {
            right = mid - 1;
        }
        // 나무 길이 충분 -> 높이 더 올릴 수 있음
        else
        {
            left = mid + 1;
        }
    }

    // answer 대신 마지막 right값 제출
    cout << right << '\n';

    return 0;
}

4. 내일 일정 : 라이브 세션 및 개인공부(이분 탐색 조금 더 풀어보기)

+ Recent posts