728x90

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

 

1463번: 1로 만들기

첫째 줄에 1보다 크거나 같고, 106보다 작거나 같은 정수 N이 주어진다.

www.acmicpc.net

나만 어려운 문제일 수 있다 ㅎㅎ

피보나치문제는 되게 간단하던데 이 문제는 답지를 봐도 이해가 안되어서 하나하나 적으면서 풀어봤다.

 

이해가 안갔던 이유:

계산한 값들을 배열에 저장해야된다고 생각했다. 

숫자가 인덱스라는 점이 안 와 닿았다. 

 

코드 보면서 얘기해보자~~

 

먼저 dp 다이나믹 프로그래밍은

반복적인 계산을 효율적으로 처리를 하는 알고리즘이다. 

큰문제를 작은 문제로 나누어 해결하고 그 결과를 저장해놨다가 재사용하여 중복계산을 피한다.

 

피보나치 보면 이해가 바로 가능하다

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

n = int(input())
#앞서 계산된 결과를 저장하기 위한 DP테이블 초기화
#n번째
d = [0]* (n+1)
print("d:",d)
#피보나치 수 : 0, 1, 1, 2, 3, 5....
#0,1로 시작하는 값
#인덱스 1번째 1  
d[1] =1
#반복문은 2번째부터 시작. 
for i in range(2, n+1): #2~n까지
	#1= 1+0
    d[i] = d[i-1]+ d[i-2]
    print(d[n])

 

처음 0,1을 주고 시작함!

그러면 인덱스 2, 부터 계산됨

 

 

그렇다면 이 문제.

 

 

피보나치는 더한 값들을 배열 d에 기록해서 간단했는데

이문제는 구하고자 하는 값이 횟수이다. 횟수를 기록해야한다.

 

숫자 10이 몇 번의 횟수를 거쳐 1이 되었냐~ 는 문제이다.

이 숫자 10과 횟수의 관계를 코드로 정립 못했었다..

횟수를 기록한 d배열의 인덱스가  "주어진 숫자" 역할을 했다. 그게 잘 안와닿았다.

 

즉 인덱스 3은 숫자 3. 그러면 인덱스 3에 횟수를 기록하게 되는 것이다. 

 

횟수를 기준으로 하니, 현재 횟수가 이전횟수 + 1이다라는게 겨우 이해되었다.

 

숫자가 2나 3으로 나눠지는 경우 : 예) 숫자가 6이면 "이전5의 횟수+ 1"을 하면 4가 되는데, 숫자 6은 2로 나눠지기때문에
최솟값으로 비교를 한다. "이전5의 횟수+ 1"  과 "d[6//3] 즉 d[2] 숫자2의 횟수에 1을 더한 값"을 비교하는 것이다.

나는 하나하나 값 넣어서 적어보면서 이해했다 ㅎㅎㅎ

# 답지
# n = int(input())
n = 10
print('n',n)
 
#계산한 횟수를 저장하는 용이래!!!
d = [0] * (n+1) 
print("d",d)

for i in range(2, n+1):  #2부터하는이유는0,1은 나누어떨어지지 않아서 횟수가 걍 0이라서!
    d[i] = d[i-1] +1 #더하기 1을 하는 이유는 기존횟수느 = 이전 횟수에 + 1 식 늘어나니까. 
   #i가 3으로 나눠지는 값이면 
    if i %3 == 0:
        #숫자 3의 횟수는 = 이전 횟수에 하나더한 횟수거나, 3으로 나눈 값의 횟수에 하나 더한 횟수! 둘중에 더 작은 값!
        d[i] = min(d[i], d[i//3]+1)
        print("3d[i]:", d[i])
    if i%2 == 0:
        d[i] = min(d[i], d[i//2]+1)

 
print(d[n])

 

 

 

 

728x90
728x90

다른 분들의 코드를 찾아보면서도 이해가 안되었는데 역시 직접 찍어가면서 하는게 제일 빠르다. 

물론 나는 답지를 보면서 ㅎㅎ

 

문제 이해를 잘못해서 엄청 헤멨다.

Magic square 마방진

 

마방진이란?

가로의 숫자들 더한 값,

세로의 숫자들 더한 값,

대각선숫자들 더한 값이 모두 같은 사각형!

 

문제가 요구하는 바:

https://www.hackerrank.com/challenges/magic-square-forming/problem?isFullScreen=true 

 

Forming a Magic Square | HackerRank

Find the minimum cost of converting a 3 by 3 matrix into a magic square.

www.hackerrank.com

input값으로 만든 행렬을 마방진으로 만들어서 두 행렬을 비교하고

바뀐 값들의 차 중에 가장 작은 수들를 더해서 출력!

 

1. 먼저 주어진 값을 마방진으로 만들어야 한다!

근데 우리는 가장 작은 수들을 찾기를 윈해서 모든 경우의 마방진을 만들어봐야했다.

 

여기서 배운 파이썬 함수

permutations

순열을 만들어주는 함수다. 

(순열이란, 조합과 달리 순서를 고려해 나열한 경우의 수를 말한다)

 

먼저 인풋 값 자체를 코드로 체크할 수 있게 정리해줬다 

이 인풋값을 차례로 넣어줬다. 

그결과 X = [5,3,4,1,5,8,6,4,2]가 되었다. 

지금은 이것은 마방진이 아니다. 

마방진으로 만들기 위해 모든 순서의 경우의 수를 만들어보자. 

1부터 9까지! 

for문 안에 P를 찍어보면 엄청많다

등등..

여기서 마방진 조건에 맞는 애들을 찾아주자. 

가로끼리 더한 값이 15

세로끼리 더한 값이 15

대각선끼리 더한 값이 15

 

파이썬 코드에 익숙하지 않아서 이 조건을 이해하는데 좀 걸렸다. 

p(0:3) 은  인덱스0,1,2라는 뜻이다. 위 인풋모양 생각하면 맨 위의 가로 한면! 여기 sum() 이 감싸니까 즉, (8 +3+4)

p(3:6)은  인덱스 3,4,5 맨 오른쪽 세로 한면 (4+9+2)

p(0::3) 이건 p배열에서 p[0]에서 시작해서 세칸씩 이동한 값  p = [8,3,4,1,5,9,6,7,2 ] 이므로 (8+1+6)

p(1::3) 얘도 같음 (3+5+7)

대각선도 다 더해서 15여야함

P[0] + P[4] + P[8] == 15 

P[2] + P[4] + P[6] == 15)

P[-3::] 이건 뒤에서 3번째에서 끝까지 더한 값 (6+7+2)

 

 

 

 

 

이렇게 마방진 조건을 다 갖춘P와 기존인풋이었던 X의 차

둘이 그냥 빼는게 아니라 모든 인덱스의 값들을 비교해서 빼야해서 

range(0,9)  for문으로 0부터 8인덱스까지 비교해서 빼줌

abs() 로 감싼이유는 만약에 2-3 나오면 음수니까 양수로 만들어주려고 씀. 

그 차리르 다 더한 값 중에 가장 작은  값으로~ min()

 

"Ans가 또 들어가는 이유는 for 루프를 통해 permutations의 모든 경우를 탐색하면서 최소값을 찾기 위해서입니다.

for 루프는 permutations(range(1,10))를 통해 1부터 9까지의 숫자로 이루어진 순열을 하나씩 가져옵니다. 각 순열을 P로 표현하고, 조건문을 통해 해당 순열이 마방진(magic square)의 조건을 만족하는지 확인합니다.

만약 조건을 만족하는 마방진이라면, sum(abs(P[i] - X[i]) for i in range(0,9))를 통해 해당 마방진과 주어진 X 리스트와의 차이의 합을 계산합니다. 그리고 이 값을 기존의 Ans와 비교하여 작은 값으로 Ans를 갱신합니다.

따라서, for 루프를 통해 모든 경우를 탐색하면서 찾은 최소 차이의 합을 Ans에 저장하게 됩니다."

 

 

from itertools import *

X = []
X.extend(list(map(int,input().split())))
X.extend(list(map(int,input().split())))
X.extend(list(map(int,input().split())))

Ans = 81
for P in permutations(range(1,10)):
   
    if sum(P[0:3]) == 15 and sum(P[3:6]) == 15 and sum(P[0::3]) == 15 and sum(P[1::3]) == 15 and P[0] + P[4] + P[8] == 15 and (P[2] + P[4] + P[6] == 15) and  sum(P[-3::]) == 15:
        # print("PPPP:",P) #P is magic square
        Ans = min(Ans, sum(abs(P[i] - X[i]) for i in range(0,9)))
print(Ans)
728x90
728x90

linked list는 Node라는 구조체가 연결되는 형식으로 데이터를 저장하는 자료구조이다. 

Node는 데이터 값과 next node의 주소값을 저장한다. 

 

linked list는 메모리 상에서는 비연속적 저장되어있지만 

각각의 node가 next node의 메모리 주소값을 가리킴으로써 

논리적은 연속성을 갖게 된다. 

 

 

 

Array list는 연속성 유지하려면 순차적으로 저장해야하지만

linked list는 자유롭다. 

주소값을 함께 저장하기 때문에! 근데 그만큼 데이터당 차지하는 메모리가 더 커지게 된다. 

 

linked list 구현시 

1. head값을 가져야함!!

 

2. head가 linked list의 첫번째 노드값을 가리켜야한다!

이렇게 되면 어느 인덱스에 있는 데이터에도 접근할 수 있다.

 

3. 마지막 노드는 다음 메모리주소가 0(none)이어야한다.

 

 

 

 

linked list의 가장 간단한 연산자 append()

get() 특정 index에 저장되어있는 값을 가져오는 연산자.

 

실제 구현시 

양방향으로 왔다갔다하는 양방향 doubled linked list도 있음

 

 

 

 

 

728x90

+ Recent posts