- 문제:

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

 

15886번: 내 선물을 받아줘 2

욱제는 구사과의 열렬한 팬이다. 오늘 욱제는 구사과에게 선물()을 전달해주려고 한다. 지난 며칠간의 관찰 끝에 욱제는 구사과의 이동 패턴을 모두 파악했다. 구사과가 있는 곳은 1×N 크기의 직

www.acmicpc.net

 

- 내 풀이:

 (01.12) DFS/ BFS 그래프 문제이나 문제를 이해하니까 구지 그 방식이 아니여도 풀 수 있을 것 같아서 EW가 있을 경우 카운트 하도록 문제를 풀었다. DFS/ BFS 공식 문제는 이번주 숙제로 풀어봐야겠다!

n = int(input())
mapp = input()

cnt = 0
for i in range(1, n):
    if mapp[i] == 'W':
        if mapp[i-1] == 'E':
            cnt +=1
        
print(cnt)

- 문제:

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

 

16112번: 5차 전직

메이플스토리 뉴비 키파가 드디어 레벨 200을 달성하고 5차 전직이라는 시스템을 이용해 캐릭터를 더욱 강력하게 만들려고 합니다. 5차 전직을 하려면 먼저 퀘스트를 통해 아케인스톤이라는 아

www.acmicpc.net

 

(1/10) 문제 이해하는데도 오래걸려서 포기하려고 했던 문제,, 2번 정도 보고 완벽히 아니고 대충 이해가 갔다! 

 

(1/11) 이해 완료~

 

- 코드: 

정답 코드 중에 파이썬이 없어서 자바코드로 먼저 이해했다.

 

<코드 이해 돕기 위한 설명>

100 200 300으로 정렬한 뒤에 1번 퀘스트를 진행하면 경험치에서 100을 빼주고, 1번을 진행한 상태니까 100을 어딘가에 한번 더해줄 수 있다.(활성화 된 스톤이 1개니까) 그다음 2번 퀘스트를 진행하면 경험치에서 200을 빼주고, 200만큼을 어딘가에 두번 더해줄 수 있다. (활성화 된 스톤이 2개니까) 이제 3번 퀘스트를 진행하면 경험치를 빼줄 필요 없이 300을 어딘가에 두번 더해주면 된다.

 

< 내가 이해한 코드와 문제 설명>

"예를 들어서 2,3 번째 아케인스톤이 활성화되어있고(2개가 활성화 되어있네! 그럼 해당 퀘스트를 제외하고 다른 아케인스톤에 해당 퀘스트의 경험치를 2번 뿌릴 수 있음) 첫번째 퀘스트를 진행했을 경우, 첫번째 아케인스톤을 획득하고 2,3번째 아케인스톤에 첫번째 퀘스트의 경험치가 쌓이고 첫번째 아케인스톤 경험치는 0이 된다."

즉, 진행한 퀘스트에 따른 아케인스톤 경험치가 0이 되므로 감소되는 경험치를 최소화하기 위해서는 오름차순으로 정렬해주는 것이 맞다. 퀘스트별 아케인스톤 경험치는 다른 아케인스톤에 본인 경험치를 줄 수가 있는데 활성화 개수에 따라 몇번 줄 수 있는지 달라진다. 그리고 경험치를 주면 본인이 가지고 있던 경험치는 0이 되게한다.

 

import java.util.Arrays;
import java.util.Scanner;

public class TemplateA {
	public static void main(String[] args){
		Scanner scan = new Scanner(System.in);
		int quest = scan.nextInt();	
		int activeS = scan.nextInt();
		
		int [] arr = new int [quest];
		
		for(int i = 0; i < quest; i++) {
			arr[i] = scan.nextInt();
		}
		
		Arrays.sort(arr);
		//오름차순으로 정렬해주어 최대 아케인스톤이 활성화 전까지
		//감소되는 경험치를 최소화한다. 
		
		int count = 0;
		//count는 최대 활성 아케인스톤 값까지 증가할 변수
		int exp  = 0;
		//최대 경험치가 들어갈 변수
		for(int i = 0; i < quest; i++) {
			if(count < activeS) {
				count ++;
				//최대 아케인 스톤값이 될때까지 하나씩 더해줌
				exp -= arr[i];				
				//최대 아케인 스톤 값이 되기 전까지는 하나의 경험치가 사라지게
				//됨으로 그 아케인 스톤의 경험치를 총경험치에서 빼줌
				
			}
			exp += (arr[i] * count);
			//이후 활성화된 아케인 스톤의 수와 경험치를 곱해줌
		}
	
		System.out.println(exp);
}
  
	}

- 코드 이해 후 파이썬으로 구현

n, act = map(int, input().split())

k = list(map(int, input().split()))
k.sort()  # 감소되는 경험치 최소화

cnt, exp = 0, 0
for i in range(n):
    if cnt< act:
        cnt+=1
        exp -= k[i]
    exp += k[i] * cnt
print(exp)

   

❤문제

유형: DP

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

 

백준 2775번 파이썬 풀이: 부녀회장이 될테야

백준 2775번 부녀회장이 될테야 알고리즘 분류: 수학, 조합론 링크: https://www.acmicpc.net/problem/2775 2775번: 부녀회장이 될테야 첫 번째 줄에 Test case의 수 T가 주어진다. 그리고 각각의 케이스마다 입력

yoonsang-it.tistory.com

❤코드

t = int(input())

num = 0
for _ in range(t):
    k = int(input())
    n = int(input())
    k0 = [x for x in range(1,n+1)]
    for a in range(k):
        for b in range(1,n):
            k0[b] += k0[b-1]
    print(k0[-1])

상향식으로 풀었당 - 배열에 계속 저장하면서 올라가도록

다이나믹 프로그래밍: 하나의 문제를 단 한번만 풀도록 하는 알고리즘

ex) 피보나치 수열

 

어떨 때 사용? 

1. 큰 문제를 작은 문제로 나눌 수 있을 때 - 크고 어려운 문제가 있으면 그것을 먼저 잘게 나누어서 해결한 뒤 처리

     -> 이 과정에서 메모이제이션(memoization) 사용해야함: 이미 계산한 결과를 배열에 저장

2. 작은 문제로부터 구한 결괏값을 큰 문제에서도 활용 가능

 

2가지 문제 풀이 방식

1. 상향식(바텀 업) 방식: 가장 작은 문제의 답부터 찾아가는 방식, 반복문 사용

2. 하향식(탑 다운) 방식: 가장 큰 문제부터 시작하여 작은 문제 순으로 답을 찾아가는 방식, 재귀 함수 활용

 

1. 상향식(바텀 업) 방식

# 계산된 결과를 memoization 하기 위해 리스트 초기화
d = [0] * 100

d[0] = 1 # a_1 = 1
d[1] = 1 # a_2 = 1

# 바텀 업 방식: 반복문 활용
for i in range(3, n+1):
    d[i] = d[i-1] + d[i-2]

n = 99
print("fibo({}): {}".format(n, fibo(n)))

2. 하향식(탑 다운) 방식

# 계산된 결과를 memoization 하기 위해 리스트 초기화
d = [0] * 100

# 탑 다운 다이나믹 프로그래밍 기법과 재귀 함수를 활용한 피보나치 수열 구현
def fibo (x):
    # 종료 조건 (전달인자가 1 또는 2일 때 1을 반환)
    if x == 1 or x == 2:
        return 1
    
    # 계산된 결괏값이 존재할 경우 해당 결과값 반환
    if d[x] != 0:
        return d[x]
        
    # 계산된 결괏값이 존재하지 않을 경우 피보나치 수열의 결과를 반환
    d[x] = fibo(x-1) + fibo(x-2)
    return d[x]

n = 99
print("fibo({}): {}".format(n, fibo(n)))

 

참고:[알고리즘] 다이나믹 프로그래밍(DP)에 대해 알아보자! (+Python 구현) (tistory.com)

 

- 문제: (1.3일)

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

 

1463번: 1로 만들기

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

www.acmicpc.net

- 코드: DP문제는 처음이라,, 되는 확률들의 횟수를 다 따로 저장해서 비교하는 방식으로 해야한다. 머릿속으로는 생각했는데 어떻게 해야할지 아예 감이 안잡혔다ㅠㅠ 상향식 하향식 방식이 있는데 상향식이 더 코드는 이해하기 쉬웠다.  DP 알고리즘에 대해서 따로 정리하기! 

n = int(input())
cnt = 0
while n>0:
    if n%3==0:
        n = n//3
        cnt+=1
        if n==1:
            break
        if n%2==0:
            n = n//2
            cnt+=1
    if n%2==0:
        n = n//2
        cnt+=1
        if n==1:
            break
        if n%3==0:
            n = n//3
            cnt+=1
    n = n-1
    cnt +=1
print(cnt)

- 정답 코드:

n = int(input())
d = [0] * (n + 1)	## d에 계산된 값을 저장해둔다. n + 1이라고 한 이유는, 1번째 수는 사실 d[1]이 아니고 d[2]이기 때문에, 계산하기 편하게 d[1]을 1번째 인 것 처럼 만들어준다.

print(d)
for i in range(2, n + 1): #11
## 여기서 왜 if 1빼는 방법, 2 나누기, 3 나누기 동등하게 하지 않고 처음에 1을 빼고 시작하는지 의아해 할 수 있다.
## 1을 빼고 시작하는 이유는 다음에 계산할 나누기가 1을 뺀 값보다 작거나 큼에 따라 어차피 교체되기 때문이다.
## 즉 셋 다 시도하는 방법이 맞다.
## 여기서 if elif else를 사용하면 안된다. if만 이용해야 세 연산을 다 거칠 수 있다, 가끔 if continue, else continue를 쓰는 분도 계신데, 난 이게 편한듯.
    d[i] = d[i - 1] + 1
    print(d[i])
    if i % 3 == 0:
        d[i] = min(d[i], d[i // 3] + 1)	## 1을 더하는 것은 d는 결과가 아닌 계산한 횟수를 저장하는 것 이기 때문이다. d[i]에는 더하지 않는 이유는 이미 1을 뺄 때 1을 더해준 이력이 있기 때문이다.
        print(d)
    if i % 2 == 0:
        d[i] = min(d[i], d[i // 2] + 1)
        print(d)
print(d[n])

- 유형: 그래프 문제 -> DFS(깊이 우선 탐색)/BFS(너비 우선 탐색)

   - DFS: 최대한 깊이 내려간 뒤, 더이상 깊이 갈 곳이 없을 경우 옆으로 이동/ BFS 보다 느림

   - BFS: 최대한 넓게 이동한 다음, 더 이상 갈 수 없을 때 아래로 이동

 

* DFS, BFS은 특징에 따라 사용에 더 적합한 문제 유형들이 있습니다.

1) 그래프의 모든 정점을 방문하는 것이 주요한 문제

단순히 모든 정점을 방문하는 것이 중요한 문제의 경우 DFS, BFS 두 가지 방법 중 어느 것을 사용하셔도 상관없습니다.

둘 중 편한 것을 사용하시면 됩니다.

2) 경로의 특징을 저장해둬야 하는 문제

예를 들면 각 정점에 숫자가 적혀있고 a부터 b까지 가는 경로를 구하는데 경로에 같은 숫자가 있으면 안 된다는 문제 등, 각각의 경로마다 특징을 저장해둬야 할 때는 DFS를 사용합니다. (BFS는 경로의 특징을 가지지 못합니다)

 

3) 최단거리 구해야 하는 문제

미로 찾기 등 최단거리를 구해야 할 경우, BFS가 유리합니다.

왜냐하면 깊이 우선 탐색으로 경로를 검색할 경우 처음으로 발견되는 해답이 최단거리가 아닐 수 있지만, 
너비 우선 탐색으로 현재 노드에서 가까운 곳부터 찾기 때문에경로를 탐색 시 먼저 찾아지는 해답이 곧 최단거리기 때문입니다.

 

이밖에도 

- 검색 대상 그래프가 정말 크다면 DFS를 고려
- 검색대상의 규모가 크지 않고, 검색 시작 지점으로부터 원하는 대상이 별로 멀지 않다면 BFS

지난 시간에 이어서 데이터 분석가가 성장하기 위해 필요한 3가지 마인드셋(Mindset)에 대해 이야기해보고자 합니다.

여기서 마인드셋(Mindset)은 하나의 가치관 또는 사고 방식이라고 이해하셔도 좋을 것 같습니다.

성장하는 데이터 분석가는
1. 분석적 사고(Analytical mindset)
2. 문제-해결 논리(Problem-solving logic)
3. 의사소통 (Communicational skill)
이 3가지를 갖추어야 합니다.

그럼 두번째 문제-해결 논리에 대해 이야기 해볼까요?

[2] 문제-해결 논리

긴 역사에서 알수 있듯, 인간은 항상 새로운 문제를 찾아내고 그 것을 해결하기를 원합니다. 그리고 현대 사회에서 문제를 해결하는 주체는 대부분 기업들이였습니다. 그 이유는 자본주의 시장에서 가장 많은 고객을 확보할수 있는 방법은 (a.k.a 가장 돈을 많이 벌수 있는 방법은) 가장 빠르게 고객이 느끼는 문제점을 찾고 누구보다 빠르고 효율적으로 해결하는 것이기 때문입니다.

특히 21세기에 들어, 고객의 문제를 찾고, 또 어느 부분을 해결해주어야 고객이 만족할지를 알려주는 데이터 분석 기법이 비즈니스에서 널리 활용되기 시작했습니다.

대표적인 예시를 들어볼까요?
- 코홀트 분석
- 퍼널 분석
- RFM 분석

데이터 분석가라면 많이 들어본 이 3가지 분석 기법은 특정 고객이 어느 부분에서 불편을 느끼고 어떻게 행동하는지를 알려주는 대표적인 분석 기법으로 자리잡았습니다.

이 분석 기법들의 공통점은
1. 고객이 느끼는 문제점을 데이터를 통해 찾아낸다
2. 어느 단계에서 문제가 있는지를 근거를 제시한다
3. 어떻게 문제를 해결할수 있을지 해결책을 제안한다
입니다.

대부분의 데이터 분석은 근본적으로 이러한 구조를 따르고 있습니다.
물론 미래를 예측하거나 보유하는 자원을 어떻게 잘 활용할지 다루는 분석도 존재합니다. 하지만 고객의 문제를 해결하는 것이 기업의 근본적인 특징이기 때문에, 많은 기업들이 문제-해결 능력을 활용하는 분석을 선호합니다.

'IT' 카테고리의 다른 글

RPA(Robotic Process Automation)  (0) 2024.05.16
Ray 병렬 프레임워크  (0) 2024.03.15
2022 연구실 안전교육 스킵하기  (0) 2022.11.30
filebrowser로 웹에서 파일 폴더 공유하기  (0) 2022.09.27
코딩 VSC 단축키 꿀팁  (0) 2022.06.30

- 문제:

  - n개의 노드수를 입력하고 첫번째 1노드를 제외한 2~ n개의 부모노드를 순서대로 나열하는 문제.

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

- 풀이:

- 문제 해결 방식:  DFS,  재귀 함수

-> 일단 dfs/bfs의 개념부터 알아가느라 정답을 먼저 보고 고민을 해봤다. 문제는 이해가 갔는데 정답 코드를 봐도 왜 저렇게 배열을 만드는지 이해가 안간다.. (12.28) -> 이해 완료!

import pandas as pd
import sys

n = int(input())

tree = [[] for _ in range(n+1)] # 빈 배열 생성
parent = [-1]*(n+1)
for _ in range(n-1):
    a, b = map(int, input().split())
    tree[a].append(b)
    tree[b].append(a)
    
def dfs(n):
    for i in tree[n]:
        if parent[i] == -1:
            parent[i] = n
            dfs(i)
dfs(1)
for i in range(2, n+1):
    print(parent[i])

--> tree의 배열을 보면 이런식으로 결과가 나오는데 각 노드 순서별로 어떤 노드와 연결되어있는지 나타내는 배열이다!

예) 0번 노드는 공백, 1번 노드와 연결된 노드는 4,6, 2번 노드와  연결된 노드는 2, 3번 노드와 연결된 노드는 5,6

 

* 문제 해결법: dfs 문제의 트리 노드 문제는 아예 함수 공식을 외우자! 

- reduce: 2차원에서 1차원리스트로 차원 줄이기 위한 모듈

from functools import reduce  # 2차원 리스트를 1차원 리스트로 차원을 줄이기 위한 모듈

a = [[10, 20], [30, 40], [50, 60]]
a2 = list(reduce(lambda x, y: x+y, a))

 

- Counter: 데이터 집합에서 개수를 자동으로 계산하기 위한 모듈

from collections import Counter

count = Counter(a2)
count

- 공백 제거

>>> d = '     py    '
>>> d.strip()
'py'
>>> d.lstrip()
'py    '
>>> d.rstrip()
'    py'

- divmod(a,b): a를 b로 나눈 몫과 나머지를 튜플로 반환

>>> divmod(7, 3)
(2, 1)

- oct(x): 정수값 x를 8진수로 변환하여 반환

>>> oct(8)
'0o10'

- hex(x): 정수값 x를 16진수로 변환하여 반환

>>> hex(16)
'0x10'

- lambda: 간단한 삼입형 함수 생성

>>> sum = lambda a,b: a+b
>>> sum
<function <lambda> at 0x000002c826BABEA0>
>>> sum(3,5)
8

- pow(x,y): x의 y제곱 결과값 반환

>>> pow(2,4)
16

 

+ Recent posts