Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[mingxoxo] BOJ_밤양갱_Python #18

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

mingxoxo
Copy link
Member

@mingxoxo mingxoxo commented Aug 4, 2024

🔗 문제 링크

https://www.acmicpc.net/problem/31926
level: 실버 1

문제 요약

달디달고 달디달고 달디단 밤양갱 ~ 🌰

daldidalgo가 총 N번 반복된 후, daldidan으로 끝나는 문자열을 출력한다.

매초 민우는 두 개의 작업 중 하나를 선택하여 시행할 수 있다.

  1. 알파벳 소문자 a부터 z 중에서 민우가 원하는 알파벳을 하나 골라서 지금까지 입력한 내용의 맨 뒤에 입력한다.
  2. 지금까지 입력한 문자열의 연속된 부분 문자열을 복사 후 입력한 내용의 맨 뒤에 붙여넣는다. 예를 들어 지금까지 작성한 문자열이 ajouapcshake라면, ajouapcshake를 복사할 수도, apc를 복사할 수도 있지만, aashake를 복사하여 붙여넣을 수는 없다.

민우가 문제에 언급된 시행 중 하나를 선택하여 매초 시행했을 때,
N번의 daldidalgo를 입력한 후 1번의 daldidan을 입력할 수 있는 최소 시간을 출력한다.

# 예제 입력 1
2

# 예제 출력 1
11 # d a l d i dal g o daldidalgo daldida n

💡 풀이 아이디어

1️⃣ 그리디로 접근하기

접근 방식은 맞지만 개수를 셀 때 예외를 고려하지 못한 상태

N = 1 인 경우 총 10번 d a l d i dal g o (8번) + daldida n (2번)
N = 2 인 경우 총 11번 d a l d i dal g o (8번) + daldidalgo(1번) + daldida n (2번)

위의 2가지의 경우를 보았을 때 daldidalgo를 한 번 입력하게 되면 존재하는 개수만큼 추가할 수 있겠다는 생각이 들었습니다. 만약 daldidalgo가 3, 4번 필요한 경우, daldidalgo가 이미 2개가 존재할 때 부분 문자열 1개 또는 2개를 선택하면 되기에 동일하게 1초가 추가로 필요하다고 생각했습니다.

(실제 최소 횟수 아님)
N=3
daldidalgo daldidalgo + daldidalgo + daldida + n = 총 12번
N=4
daldidalgo daldidalgo + daldidalgo daldidalgo + daldida + n = 총 12번

따라서 daldidalgo를 입력할 수 있는 개수가 2의 배수로 늘어날 수 있습니다.
이를 바탕으로 작성한 1차 시도 코드는 아래와 같습니다.
햐지만 이 코드는 틀렸습니다..

N = int(input())
time = 10
cnt = 1
N -= 1

while 0 < N:
    N -= cnt
    time += 1
    cnt *= 2
 
print(time)

2️⃣ 생각하지 못했던 최소 입력..!

도대체 뭐가 틀린거지?!?! 라고 혼자 생각하던 와중 daldidan 에 있는 daldida 또한 daldidalgo의 부분 문자열이 될 수 있다는 사실을 깨달았습니다..

따라서 daldidann을 제외한 daldida 또한 daldidalgo의 횟수에 포함시켜 계산하였습니다.
이렇게 바꾸면서 time의 초기값이 9로 변경되고 N -= 1 코드를 지웠습니다.
코드를 수정하고 제출했더니 성공 ~!

📝 새로 학습한 내용

#include <stdio.h>
int main(){
	int N, a=9;
	for (scanf("%d",&N);N>0;N>>=1) a++;
	printf("%d",a);
}

다른 분의 풀이 를 통해 비트 연산으로도 쉽게 계산이 가능하다는 것을 알게되었습니다. 제가 계산할 때에도 2의 배수를 계속 곱하고 값을 빼주는 과정을 반복문 내부에서 진행하는데, 이 과정이 비트 시프트 연산(>>)로 이루어질 수 있습니다. 결국 비트의 자릿수만큼이 더해집니다. 아주 깔끔하게 작성될 수 있습니다..!

이 방식을 python에서 적용시키면 bin 함수를 적용해서 아래와 같이 작성할 수 있을 것 같습니다.
bin 함수는 10진수를 2진수로 변환시켜주는데 0b가 앞에 함께 출력되기 때문에 2를 빼 주었습니다.

N = int(input())
time = 9 
print(time + len(bin(N)) - 2)

📚 참고 자료

🙅🏻‍♀️

@mingxoxo mingxoxo added 💻 BOJ 백준 온라인 저지의 문제 ✨ Python 파이썬으로 푼 문제 labels Aug 4, 2024
@mingxoxo mingxoxo self-assigned this Aug 4, 2024
@dalsu0222
Copy link
Collaborator

비트 연산은 생각치도 못했는데 확실히 적용하니까 코드가 진짜 깔삼해지는거같아요!!!
문제를 백준에 들어가서 봤을땐 처음에 이해하기 힘들었는데, 자세하게 설명해주셔서 이해가 잘 됐던거같아요
N을 홀수냐 짝수냐에따라서 분석해보고 초기설정을 8로 해서(daldidalgo)코드를 짜는 접근방식이 저는 먼저 떠올랐었는데,
초기설정을 (daldidalgo + n)9로 하고 while문의 cnt로 최대 추가 개수를 관리해주니까 더 간결하고 멋진 코드가 된거같아요 👍🏻

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
💻 BOJ 백준 온라인 저지의 문제 ✨ Python 파이썬으로 푼 문제
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants