[백준 16974][C++] 레벨 햄버거

2023. 8. 7. 20:59·코딩 공부/백준(C++)

문제 링크

https://www.acmicpc.net/problem/16974


◆문제 해결 및 설명◆

 

알고리즘 분류 : 다이나믹 프로그래밍, 분할 정복, 재귀

 

간단하게 문제를 풀이하자면 N 레벨 햄버거 내부는

{Bun (N-1레벨 햄버거) Petty (N-1레벨 햄버거) Bun} 로 이루어져 있을 때,

뒤에서 M장을 먹었을 때 패티의 갯수를 구하는 문제이다.

 

N 레벨의 버거의 길이 공식은 N : (N-1) *2 + 3 이므로 대략 2의50승을 넘어갈 것이므로 이를 직접 뒤에서 지우며 실행할 수 는 없고, 동적 프로그래밍의 힘을 써야 한다. 아래는 4레벨 까지의 버거 내용이다. (레벨1의 버거는 띄어쓰기를 하지 않았다.)(P 와 B는 추가된 번과 패티이다.

 

0 : P
1 : BPPPB
2 : B BPPPB P BPPPB B
3 : B B BPPPB P BPPPB B P B BPPPB P BPPPB B B
4 : B B B BPPPB P BPPPB B P B BPPPB P BPPPB B B P B B BPPPB P BPPPB B P B BPPPB P BPPPB B B B

 

여기서 찾을 수 있는 특징은 

1. 뒤에있는 패티를 전부 치우면 레벨2 버거가 나온다.

즉 아랫단계의 버거를 내부에서 찾을 수 있다. 

4 : (생략) P B B BPPPB P BPPPB B P B BPPPB P BPPPB B B B (레벨1)

이를 응용하여 레벨 1 버거가 아닌 더 높은 버거도 찾을 수 있다.

4 : (생략) P B B BPPPB P BPPPB B P B BPPPB P BPPPB B B B (레벨2)

∴ (먹어야 하는 번의 갯수) = (현재 버거의 레벨) - (찾을 버거의 레벨)


2. N-1 버거 만큼과 P 그리고 B를 먹으면 다시 N-1 버거와 B하나가 남는다는 것이다.

4 : B B B BPPPB P BPPPB B P B BPPPB P BPPPB B B (생략) (레벨3)


3. 패티의 개수는 N : (N-1 버거 패티 수) * 2 + 1 , 전체 길이는 N : (N-1) *2 + 3가 된다.

이를 통해 버거의 길이와 패티수를 다이나믹 프로그래밍으로 구현하는 것이 가능하다.

#include <iostream>
#include <vector>
std::vector<std::pair<int64_t, int64_t>> dp(52); // petty,len

	dp[0] = std::make_pair(1, 1);
    for (int i = 1; i <= level + 1; i++)
    {
        dp[i] = std::make_pair(dp[i - 1].first * 2 + 3, dp[i - 1].second * 2 + 1);
        // std::cout << i << " : " << dp[i].first << "," << dp[i].second << std::endl;
    }

입력에는 (레벨-N 버거), (먹은 아래 M장)이 주어지고 이를 함수를 통해 재귀적으로 풀었다.

함수의 매개변수는 (버거의 레벨), (먹을 수 있는 가장 큰 버거) 이다.

 

함수를 통해

1. 먹을 양 == 먹을 수 있는 가장 큰 레벨 버거 + 뒤에있는 번

2. 먹을 게 (버거 + 번) 보다 많다면 이후 패티를 먹는다.

3. 먹을게 (버거 + 번) 보다 적다면, 뒤에 있는 번만 먹는다.

로 나누어서 구현하였다. 

 

◆코드 전문◆

#include <iostream>
#include <vector>
#include <string>
std::vector<std::pair<int64_t, int64_t>> dp(52); // petty,len
int64_t eat, answer = 0;

int eati(int level, int cnt)
{
    // eat == cnt 레벨 버거 + 뒤에있는 번
    if (eat == dp[cnt].first + (level - cnt))
    {
        answer += dp[cnt].second;
        eat -= dp[cnt].first;
        eat -= (level - cnt);
    }
    // 먹을 게 (버거 + 번) 보다 많다면 이후 패티를 먹는다.
    else if (eat > dp[cnt].first + (level - cnt))
    {
        eat -= (level - cnt);
        answer += dp[cnt].second;
        eat -= dp[cnt].first;
        eat--;
        answer++;
    }
    // 먹을게 (버거 + 번) 보다 적다면, 뒤에 있는 번만 먹는다.
    else if (eat < dp[cnt].first + (level - cnt))
    {
        eat -= (level - cnt);
    }

    if (eat <= 0)
    {
        return 0;
    }

    level = cnt;
    for (int i = 0; eat >= dp[i].first; i++)
    {
        level = i;
    }
    eati(cnt, level);
    return 0;
}

int main()
{
    int level;
    std::cin >> level >> eat;
    int cnt = level;

    dp[0] = std::make_pair(1, 1);
    for (int i = 1; i <= level + 1; i++)
    {
        dp[i] = std::make_pair(dp[i - 1].first * 2 + 3, dp[i - 1].second * 2 + 1);
    }
    if (eat == dp[level].first)
    {
        std::cout << dp[level].second;
        return 0;
    }
    //(먹을 수 있는 가장 큰 버거) 값을 찾는다. (cnt에 저장)
    for (int i = 0; eat >= dp[i].first; i++)
    {
        cnt = i;
    }

    eati(level, cnt);
    std::cout << answer;
}

 

'코딩 공부 > 백준(C++)' 카테고리의 다른 글

[백준 2607][C++] 비슷한 단어  (0) 2023.08.11
[백준 15686][C++] 치킨 배달  (0) 2023.08.09
[백준 9658][C++] 돌 게임 4  (0) 2023.08.09
[백준 2941][C++] 크로아티아 알파벳, segfault, size_t  (0) 2023.07.22
[백준] 11659번 : 구간 합 구하기 4 [C++]  (0) 2023.02.04
'코딩 공부/백준(C++)' 카테고리의 다른 글
  • [백준 15686][C++] 치킨 배달
  • [백준 9658][C++] 돌 게임 4
  • [백준 2941][C++] 크로아티아 알파벳, segfault, size_t
  • [백준] 11659번 : 구간 합 구하기 4 [C++]
메카인
메카인
  • 메카인
    메카인의 지식창고
    메카인
  • 전체
    오늘
    어제
    • 분류 전체보기
      • 코딩 공부
        • TIL(Today I Learn)
        • TIL
        • 백준(C++)
        • Python
        • 알고리즘
        • 프로젝트 회고
      • C++
        • C++
        • C++ STL
        • C,C++ mCoding yotube
      • 게임개발
        • 언데드서바이벌_골드메탈_클론코딩
        • 3D_골드메탈_클론코딩
        • 유니티_문제해결
        • 게임 수학
      • Unreal 공부
        • UE5 GameDev
        • Unreal Engine 4 C++ The Ult..
      • 교재 문제 풀이
        • 운영체제
      • 정보처리기사
        • 정처기 요약
        • 정처기 오답노트
      • 학교수업
        • 데이터베이스
        • 프로그래밍 언어론
        • 리눅스 시스템
        • 네트워크
      • 일상
        • 주식
        • 독서
      • (비공개 전용)
        • memory
        • Build
        • OOP
        • Smart Pointer
        • lamda
        • 게임 수학
        • 모던 C++
        • 모던 C++ STL
        • 모던 C++ Concurrency, Paralle..
        • 책
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
    • 글쓰기
    • 블로그 관리
  • 링크

  • 공지사항

    • 공지사항 - 인생과 블로그의 목표
  • 인기 글

  • 태그

  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
메카인
[백준 16974][C++] 레벨 햄버거
상단으로

티스토리툴바