728x90
반응형

문제:

N*M 크기의 직사각형이 있다. 각 칸은 한 자리 숫자가 적혀있다. 이 직사각형에서 꼭짓점에 쓰여 있는 수가 모두 같은 가장 큰 정사각형을 찾는 프로그램을 작성하시오. 이때, 정사각형은 행 또는 열에 평행해야 한다.

입력:

첫째 줄에 N과 M이 주어진다. N과 M은 50보다 작거나 같은 자연수이다. 둘째 줄부터 N개의 줄에 수가 주어진다.

출력:

첫째 줄에 정답 정사각형의 크기를 출력한다.

풀이방법:

N과 M의 크기가 50보다 작기 때문에 브루트 포스로 전부 탐색을 해도 된다. 1x1의 정사각형은 반드시 존재하기 때문에 넘어가고 가로, 세로 길이가 2인 정사각형부터 탐색을 시작한다. 한 변의 길이가 n이지만 좌표상의 차이는 n-1이 나게 된다. 따라서 이 점을 이용해서 꼭짓점의 값들이 같은지 탐색하고 같다면 answer를 변경하도록 한다.

만약 모두 탐색을 했는데 초기 answer이 변하지 않는다면 가장 큰 정사각형은 1x1이므로 1을 출력하도록 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
n,m=map(int,input().split())
numbers=[]
 
for _ in range(n):
    numbers.append(input())
 
dif=1
answer=0
while True:
    for i in range(n-dif):
        for j in range(m-dif):
            if numbers[i][j]==numbers[i][j+dif]==numbers[i+dif][j]==numbers[i+dif][j+dif]:
                answer=(dif+1)**2
    dif+=1
    if n-dif<=0 or m-dif<=0:
        break
 
if answer==0:
    print(1)
else:
    print(answer)
cs

문제링크:

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

 

1051번: 숫자 정사각형

N*M크기의 직사각형이 있다. 각 칸은 한 자리 숫자가 적혀 있다. 이 직사각형에서 꼭짓점에 쓰여 있는 수가 모두 같은 가장 큰 정사각형을 찾는 프로그램을 작성하시오. 이때, 정사각형은 행 또는 열에 평행해야 한다.

www.acmicpc.net

 

728x90
반응형

'Algorithm > Python' 카테고리의 다른 글

[BOJ]1718. 암호  (0) 2020.04.09
[BOJ]1302 베스트셀러  (0) 2020.04.07
[BOJ]2644. 촌수계산  (0) 2020.03.24
[BOJ]2352. 반도체 설계  (0) 2020.03.19
[BOJ]1748. 수 이어 쓰기 1  (0) 2020.03.17
728x90
반응형

문제:

우리 나라는 가족 혹은 친척들 사이의 관계를 촌수라는 단위로 표현하는 독특한 문화를 가지고 있다. 이러한 촌수는 다음과 같은 방식으로 계산된다. 기본적으로 부모와 자식 사이를 1촌으로 정의하고 이로부터 사람들 간의 촌수를 계산한다. 예를 들면 나와 아버지, 아버지와 할아버지는 각각 1촌으로 나와 할아버지는 2촌이 되고, 아버지 형제들과 할아버지는 1촌, 나와 아버지 형제들과는 3촌이 된다.

 

여러 사람들에 대한 부모 자식들 간의 관계가 주어졌을 때, 주어진 두 사람의 촌수를 계산하는 프로그램을 작성하시오.

입력:

사람들은 1, 2, 3, ..., n (1<=n<=100)의 연속된 번호로 각각 표시된다. 입력 파일의 첫째 줄에는 전체 사람의 수 n이 주어지고, 둘때 줄에는 촌수를 계산해야 하는 서로 다른 두 사람의 번호가 주어진다. 그리고 셋째 줄에는 부모 자식들 간의 관계의 개수 m이 주어진다. 넷째 줄부터는 부모 자식간의 관계를 나타내는 두 번호 x,y가 각 줄에 나온다. 이때 앞에 나오는 번호 x는 뒤에 나오는 정수 y의 부모 번호를 나타낸다.

 

각 사람의 부모는 최대 한 명만 주어진다.

출력:

입력에서 요구한 두 사람의 촌수를 나타내는 정수를 출력한다. 어떤 경우에는 두 사람의 친척 관계가 전혀 없어 촌수를 계산할 수 없을 때가 있다. 이 때에는 -1을 출력해야 한다.

풀이방법:

두 사람이 얼마나 긴 간격으로 연결되어 있는지 확인하는 문제이기 때문에 dfs나 bfs로 풀어야 할 것 같다고 생각했다. dfs로도 풀 수 있는지 정확히 모르지만, 두 사람 사이의 몇 level(단계)가 있는지 확인하면 되는 문제 이므로 bfs를 사용하기로 했다.

형제들 같은 경우에는 2촌으로 계산되는데 그 이유가 (나에서 부모님으로 1촌) + (부모님에서 형제로 1촌) 이기 때문이다. 따라서 이러한 관계를 알기 위해서는 양방향으로 이동할 수 있도록 relation을 만들었고, 중복방문을 하지 않기 위해서 visited를 만들었다.

처음 시작해야 하는 사람의 번호로 시작한다. 그리고 그 사람과 관계가 있는 사람들 중 방문하지 않았던 사람만 temp라는 배열에 담고 방문한 것으로 visited를 변경한다. 그리고 이 temp에 나와의 관계가 알고 싶은 사람의 번호가 있는지 확인하고, 있다면 break 없다면 temp의 길이를 재서 탐색할 사람이 있는지 확인한다. temp에 더 탐색할 사람이 있다면 위의 행동을 다시 반복하고, 더 이상 탐색할 사람이 없다면 친척 관계가 전혀 없다는 것으로 출력하면 된다.

그리고 최종 출력에서 +1을 했는데, 이 이유는 temp에 내가 원하는 사람의 번호가 있기 때문에 그 관계로 이동한다는 행동이 빠져있었기 때문에 +1을 해서 출력하도록 했다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
N=int(input())
a,b=map(int,input().split())
m=int(input())
 
relation = [[]for _ in range(N+1)]
visited = [0 for _ in range(N+1)]
 
for _ in range(m):
    c,d = map(int,input().split())
    relation[c].append(d)
    relation[d].append(c)
    
answer = 0
re=relation[a]
while True:
    temp=[]
    for i in re:
        for j in relation[i]:
            if visited[j]==0:
                visited[j]=1
                temp.append(j)
    answer+=1
    if b in temp:
        find=True
        break
    if len(temp)==0:
        find=False
        break
    re = temp
if find:
    print(answer+1)
else:
    print(-1)
cs

문제링크:

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

 

2644번: 촌수계산

사람들은 1, 2, 3, …, n (1≤n≤100)의 연속된 번호로 각각 표시된다. 입력 파일의 첫째 줄에는 전체 사람의 수 n이 주어지고, 둘째 줄에는 촌수를 계산해야 하는 서로 다른 두 사람의 번호가 주어진다. 그리고 셋째 줄에는 부모 자식들 간의 관계의 개수 m이 주어진다. 넷째 줄부터는 부모 자식간의 관계를 나타내는 두 번호 x,y가 각 줄에 나온다. 이때 앞에 나오는 번호 x는 뒤에 나오는 정수 y의 부모 번호를 나타낸다. 각 사람의 부모는 최대

www.acmicpc.net

 

728x90
반응형

'Algorithm > Python' 카테고리의 다른 글

[BOJ]1302 베스트셀러  (0) 2020.04.07
[BOJ]1051. 숫자 정사각형  (0) 2020.03.26
[BOJ]2352. 반도체 설계  (0) 2020.03.19
[BOJ]1748. 수 이어 쓰기 1  (0) 2020.03.17
[BOJ]1267. 핸드폰 요금  (0) 2020.03.12
728x90
반응형

문제:

반도체를 설계할 때 n개의 포트를 다른 n개의 포트와 연결해야 할 때가 있다.

예를 들어 왼쪽 그림이 n개의 포트와 다른 n개의 포트를 어떻게 연결해야 하는지를 나타낸다. 하지만 이와 같이 연결을 할 경우에는 연결선이 서로 꼬이기 때문에 이와 같이 연결할 수 없다. n개의 포트가 다른 n개의 포트와 어떻게 연결되어야 하는지가 주어졌을 때, 연결선이 서로 꼬이지(겹치지, 교차하지) 않도록 하면서 최대 몇 개까지 연결할 수 있는지를 알아내는 프로그램을 작성하시오.

입력:

첫째 줄에 정수 n(1<=n<=40,000)이 주어진다. 다음 줄에는 차례로 1번 포트와 연결되어야 하는 포트 번호, 2번 포트와 연결되어야 하는 포트 번호, ... , n번 포트와 연결되어야 하는 포트 번호가 주어진다. 이 수들은 1 이상 n 이하이며 서로 같은 수는 없다고 가정하자.

출력:

첫째 줄에 최대 연결 개수를 출력한다.

풀이방법:

복잡해 보이지만 LIS 문제라고 생각하면 쉽게 풀 수 있다. LIS를 푸는 방법에는 여러 가지가 있지만 가장 대표적인 방법인 DP를 사용해서 문제를 풀어보았다.

1
2
3
4
5
6
7
8
9
10
11
n=int(input())
ports=list(map(int,input().split()))
 
dp=[0]*n
 
for i in range(1,n):
    for j in range(i):
        if ports[i] > ports[j] and dp[i] < dp[j]+1:
            dp[i]=dp[j]+1
            
print(dp[-1]+1)
cs

DP로 푸는 방법은 O(N^2)의 시간 복잡도이기 때문에 시간이 오래 걸리게 된다. 따라서 O(NlogN)으로 푸는 방법이 있다해서 다음을 참고 하였다.

https://dyngina.tistory.com/16

 

LIS (Longest Increasing Subsequence)

오랫만에 포스팅을 해보네요. 시험기간 (정확히 말하면 시험보는 기간입니다.) 이 되니까 별게 다 하고 싶어지네요. 이번에는 DP중에서 특별히 LIS에 대한 내용을 다뤄보려고 합니다. LIS. Longest Increasing Sub..

dyngina.tistory.com

여기서 O(NlogN)이 두 개 있었는데 lower_bound는 python의 bisect를 쓰면 될 것 같다. 이번에는 인덱스 트리를 사용해서 문제를 풀어 보았다. 인덱스 트리를 만들기 위한 과정에서 시간이 많이 소요 되는 것 같아서 이 역시도 pypy3로 통과했다. 아마도 bisect를 사용하면 python으로도 통과할 수 있을 것 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
n=int(input())
ports=list(map(int,input().split()))
 
for i in range(n):
    ports[i]=(ports[i],i+1)
ports.sort()
 
dp=[0]*n
for i in range(n):
    idx=ports[i][1]
    maxTemp=0
    for j in range(idx):
        if dp[j] > maxTemp:
            maxTemp=dp[j]
    dp[idx-1]=maxTemp+1
print(max(dp))
cs

문제링크:

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

 

2352번: 반도체 설계

첫째 줄에 정수 n(1 ≤ n ≤ 40,000)이 주어진다. 다음 줄에는 차례로 1번 포트와 연결되어야 하는 포트 번호, 2번 포트와 연결되어야 하는 포트 번호, …, n번 포트와 연결되어야 하는 포트 번호가 주어진다. 이 수들은 1 이상 n 이하이며 서로 같은 수는 없다고 가정하자.

www.acmicpc.net

 

728x90
반응형

'Algorithm > Python' 카테고리의 다른 글

[BOJ]1051. 숫자 정사각형  (0) 2020.03.26
[BOJ]2644. 촌수계산  (0) 2020.03.24
[BOJ]1748. 수 이어 쓰기 1  (0) 2020.03.17
[BOJ]1267. 핸드폰 요금  (0) 2020.03.12
[BOJ]2579. 계단 오르기  (0) 2020.03.10
728x90
반응형

문제:

1부터 N까지의 수를 이어서 쓰면 다음과 같이 새로운 하나의 수를 얻을 수 있다.

 

1234567891011121314151617181920212223...

 

이렇게 만들어진 새로운 수는 몇 자리 수일까? 이 수의 자릿수를 구하는 프로그램을 작성하시오.

입력:

첫째 줄에 N(1<=N<=100,000,000)이 주어진다.

출력:

첫째 줄에 새로운 수의 자릿수를 출력한다.

풀이방법:

처음에는 브루트 포스로 알고리즘 분류가 되어 있어서 그냥 N까지의 수를 다 붙인 다음에 길이를 구하는 방식으로 했는데 시간초과가 발생했다.

1
2
3
4
5
6
#시간초과
n=int(input())
answer=''
for i in range(1,n+1):
    answer+=str(i)
print(len(answer))
cs

그래서 처음 받은 N을 기준으로 자릿수를 줄여나가면서 더하는 방식으로 바꾸어서 해결을 했다.

ex) 3자리수의 갯수*3 + 2자리수의 갯수*2 ....

1
2
3
4
5
6
7
8
9
n=input()
 
answer=0
length=len(n)
while length:
    answer+=(int(n)-10**(length-1)+1)*length
    n=10**(length-1)-1
    length-=1
print(answer)
cs

문제링크:

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

 

1748번: 수 이어 쓰기 1

첫째 줄에 N(1≤N≤100,000,000)이 주어진다.

www.acmicpc.net

 

728x90
반응형

'Algorithm > Python' 카테고리의 다른 글

[BOJ]2644. 촌수계산  (0) 2020.03.24
[BOJ]2352. 반도체 설계  (0) 2020.03.19
[BOJ]1267. 핸드폰 요금  (0) 2020.03.12
[BOJ]2579. 계단 오르기  (0) 2020.03.10
[BOJ]13458. 시험 감독  (0) 2020.03.05
728x90
반응형

문제:

동호는 새악대로 T 통신사의 새 핸드폰 옴머나를 샀다. 새악대로 T 통신사는 동호에게 다음 두 가지 요금제 중 하나를 선택하라고 했다.

 

1. 영식 요금제

2. 민식 요금제

 

영식 요금제는 30초마다 10원씩 청구된다. 이 말은 만약 29초 또는 그 보다 적은 시간 통화를 했으면 10원이 청구된다. 만약 30초부터 59초 사이로 통화를 했으면 20원이 청구된다.

 

민식 요금제는 60초마다 15원씩 청구된다. 이 말은 만약 59초 또는 그 보다 적은 시간 통화를 했으면 15원이 청구된다. 만약 60초부터 119초 사이로 통화를 했으면 30원이 청구된다.

 

동호가 저번 달에 새악대로 T 통신사를 이용할 때 통화 시간 목록이 주어지면 어느 요금제를 사용 하는 것이 저렴한지 출력하는 프로그램을 작성하시오.

입력:

동호가 저번 달에 이용한 통화의 개수 N이 주어진다. N은 20보다 작거나 같은 자연수이다. 둘째 줄에 통화 시간 N개가 주어진다. 통화 시간은 10,000보다 작거나 같은 자연수이다.

출력:

첫째 줄에 싼 요금제의 이름을 출력한다. 그 후에 공백을 사이에 두고 요금이 몇 원 나오는지 출력한다. 만약 두 요금제의 요금이 모두 같으면 영식을 먼저 쓰고 민식을 그 다음에 쓴다.

 

영식은 Y로, 민식은 M으로 출력한다.

풀이방법:

처음에 정답 비율이 30%대이길래 난이도가 있는 문제인 줄 알았는데 생각보다 간단했던 문제였다.

통화한 시간들을 배열에 담고 각 30초, 60초로 나눈 몫에 1을 더하고 10원, 15원을 곱한 것들을 계속 누적해서 더하고 나 중에 이를 비교해 형식에 맞게 출력하면 되는 문제였다.

아마도 정답률이 낮았던 이유가 형식을 맞지 못하게 출력해서 그런 것 같으므로 python의 format을 사용해서 형식을 맞춰 주었다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
n=int(input())
times=list(map(int,input().split()))
 
Y,M=0,0
for time in times:
    Y+=(time//30+1)*10
    M+=(time//60+1)*15
        
        
if Y > M:
    print("M {}".format(M))
elif Y==M:
    print("Y M {}".format(Y))
else:
    print("Y {}".format(Y))
cs

문제링크:

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

 

1267번: 핸드폰 요금

동호가 저번 달에 이용한 통화의 개수 N이 주어진다. N은 20보다 작거나 같은 자연수이다. 둘째 줄에 통화 시간 N개가 주어진다. 통화 시간은 10,000보다 작거나 같은 자연수이다.

www.acmicpc.net

 

728x90
반응형

'Algorithm > Python' 카테고리의 다른 글

[BOJ]2352. 반도체 설계  (0) 2020.03.19
[BOJ]1748. 수 이어 쓰기 1  (0) 2020.03.17
[BOJ]2579. 계단 오르기  (0) 2020.03.10
[BOJ]13458. 시험 감독  (0) 2020.03.05
[BOJ]6588. 골드바흐의 추측  (0) 2020.03.03
728x90
반응형

Youtube에 있는 David Silver의 Reinforcement Learning 강의를 보고 작성하였습니다.

6. Value Function Approximation

지금까지는 Grid World를 통해서 작은 상황을 설정했고 table로 저장하는 것이 가능했다. 그리고 value function과 policy를 구하는 과정을 살펴보았다. 이러한 문제들을 Tabular Method라고 부른다. 하지만 실제 문제에 대해서 강화학습을 적용하기에는 너무 크다.

지금 강화학습으로 해결할 수 있거나 해결하려고 하는 문제에 대해서 state의 갯수를 알아보면 다음과 같다. Backgammon은 1020, 알파고는 10170, 헬리콥터(자율주행)은 사실상 무한대의 상태들을 가지고 있다. 따라서 이러한 문제에 대해서 value function과 policy를 구하고자 하는 것은 어렵다. 따라서 이 값들을 추정하는 방법들에서 배우도록 한다.

function approximation을 하는 방법은 어렵지 않다. 새로운 변수 w를 대입해서 이 변수가 table의 정보를 대변하도록 만들면 된다. 즉 다음과 같이 함수화 할 수 있다.

w는 학습을 통해서 update하며, true value와 근사하도록 맞춰나간다. 최근에는 이 학습을 하는 과정에 deep learning을 사용하기도 한다.

Value Function Approximation에는 다음과 같은 종류들이 있다고 한다.

function approximator에는 여러 개가 있지만 그 중 미분가능한 Linear combinations of features, Neural network를 이번 장에서 소개하도록 한다. 그리고 이들은 non-stationary, non-iid한 data라고 하는데, 분포가 계속해서 바뀌며 독립적이지 않다.

Incremental Methods

w를 업데이트를 하는 방법중 가장 좋은 것은 Gradient Descent이다. 이 방법은 간단하고 프로그램 상으로도 강력하다. 하지만 시작점에서 조금만 달라져도 다른 점에 도착할 수 있고, 이 점이 local optima일 수도 있다.

w로 표현되는 loss function인 J(w)는 true value와의 error로써 이를 최소화하는 것이 목적이다.

이를 미분해서 값을 update 할 수 있는데 expectation을 쓰는 방법과 sampling을 하는 방법이 있고 다음과 같다.

MC와 TD에서 했던 것처럼 vπ(S)를 대체해서 사용할 수 있다.

MC with Value Function Approximation

MC의 Gt는 unbiased 하고, true value의 noisy sample이다. 그러므로 training data를 지도학습으로 적용할 수 있다. 그래서 위와 같이 사용가능하며, local optimum으로 수렴하게 된다. 그리고 non-linear한 경우에도 적용할 수 있다고 한다.

TD Learning with Value Function Approximation

TD-target은 guess를 사용하는 것이기 때문에 true value의 biased sample이다. 하지만 여전히 training data를 지도학습으로 적용이 가능하고 위에서 소개한 것처럼 TD(0)를 적용할 수 있다.

Linear TD(0)는 (거의) global optimum에 수렴한다.

TD(λ) with Value Function Approximation

Gtλ도 true value의 biased sample이다. 그러므로 역시 training data를 지도학습으로 적용할 수 있으며 Forward view linear TD(λ), Backward view linear TD(λ)로 각각 적용할 수 있고, 서로 equivalent하다.

Control with Value Function Approximation

하지만 value function을 사용하면 control 문제를 다룰 때 발생했던 model-free가 발생한다. 따라서 이번에도 value function을 q-function으로 바꾸도록 한다.

그리고 그 뒤로는 value function을 했던 내용과 동일합니다.

Batch Methods

Gradient descent는 간단하고 매력적이지만 한번 쓰고 버린다. 따라서 sample efficient하지 않다고 한다. 따라서 Batch method는 1000개의 데이터가 있으면 그 중 10개를 sample로 해서 사용하는 방식이다. 이를 통해 value function의 best fitting을 찾을 수 있다고 한다.

value function approximation을 사용하고, experience D는 <state, value>의 쌍으로 구성된다. 이 때 best fitting value인 파라미터 w를 찾기 위해서 Least squares 알고리즘을 사용한다.

Least squares 알고리즘은 추측값과 참값 사이의 sum-squared error를 최소화하는 w를 찾는 알고리즘이다.

Stochastic Gradient Descent with Experience Replay

<state, value>로 쌍이 묶어진 experience D가 있을 때, 다음을 반복한다.

그러면 이는 다음과 같이 수렴한다.

이러한 방법을 Experience replay라고 하며 강화학습에서 자주 사용하는 방법이다.

Experience replay in Deep Q Networks

Non-linear랑 off-policy일 때 학습을 진행하면 수렴을 하지 않고 발산한다는 문제점이 발생한다. 따라서 이러한 문제를 해결하기 위해 DQN은 experience replay와 fixed Q-target을 사용한다고 한다.

  • Experience reaply: 어떤 action에 어떤 reward와 그 state등 정보들이 있는 transition을 replay memory에 저장하고, random하게 mini batch를 뽑는다. 그리고 MSE를 통해 학습한다.
  • Fixed Q-target: target을 계산할 때에 예전 parameter를 쓰는 것, 두 개의 파라미터 set이 있다. 하나는 고정시키고 다른 하나는 업데이트 중인 파라미터 set을 가진다. non-linear 함수일 때에 업데이트 방향이 계속 바뀌기 때문에 수렴되기 어렵다. 따라서 1000번 정도는 고정된 parameter set을 사용하며 진행하다가 그 이후에 고정된 parameter set을 업데이트 하던 parameter set으로 바꾼다. 예전 버전을 w-, 현재 버전을 w라 했을 때, target에서는 고정된 것을 사용하기 때문에 fixed Q-target이라 한다.
728x90
반응형
728x90
반응형

문제:

계단 오르기 게임은 계단 아래 시작점부터 계단 꼭대기에 위치한 도착점까지 가는 게임이다. <그림1>과 같이 각각의 계단에는 일정한 점수가 쓰여 있는데 계단을 밟으면 그 계단에 쓰여 있는 점수를 얻게 된다.

예를 들어 <그림 2>와 같이 시작점에서부터 첫 번째, 두 번째, 네 번째, 여섯 번째 계단을 밟아 도착점에 도달하면 총 점수는 10+20+25+20 = 75점이 된다.

계단 오르는 데는 다음과 같은 규칙이 있다.

 

1. 계단은 한 번에 한 계단씩 또는 두 계단씩 오를 수 있다. 즉, 한 계단을 밟으면서 이어서 다음 계단이나, 다음 다음 계단으로 오를 수 있다.

2. 연속된 세 개의 계단을 모두 밟아서는 안 된다. 단, 시작점은 계단에 포함되지 않는다.

3. 마지막 도착 계단은 반드시 밟아야 한다.

 

따라서 첫 번째 계단을 밟고 이어 두 번째 계단이나, 세 번째 계단으로 오를 수 있다. 하지만, 첫 번째 계단을 밟고 이어 네 번째 계단으로 올라가거나, 첫 번째, 두 번째, 세 번째 계단을 연속해서 모두 밟을 수는 없다.

 

각 계단에 쓰여 있는 점수가 주어질 때 이 게임에서 얻을 수 있는 총 점수의 최댓값을 구하는 프로그램을 작성하시오.

입력:

입력의 첫째 줄에 계단의 개수가 주어진다.

 

둘째 줄부터 한 줄에 하나씩 제일 아래에 놓인 계단부터 순서대로 각 계단에 쓰여 있는 점수가 주어진다. 계단의 개수는 300이하의 자연수이고, 계단에 쓰여 있는 점수는 10,000이하의 자연수이다.

출력:

첫째 줄에 계단 오르기 게임에서 얻을 수 있는 총 점수의 최댓값을 출력한다.

풀이방법:

조건3인 마지막 계단을 무조건 밟아야 하기 때문에 경우의 수는 다음 2개만 존재하게 된다.

 

1. 마지막칸의 전칸을 밟고 마지막 칸으로 이동하는 경우

? ? O O

2. 마지막의 전전칸을 밟고 마지막칸을 밟는 경우

? O X O

 

그런데 1번의 경우에는 조건2가 있기 때문에 이를 고려해 줘야 한다. 

? O X O O

이 것을 코드로 구현하게 되면 다음과 같다. 

1번 -> dp[n-3] + stair[n-1] + stair[n]

2번 -> dp[n-2] + stair[n]

따라서 이 둘중 max 값을 골라서 진행하면 된다.

 

이를 위해서 dp[0], dp[1], dp[2]를 초기화 해줬는데, 만약 계단의 개수가 이보다 적게 되면 런타임에러가 발생하게 된다.

따라서 stair를 공백의 빈 배열을 만들어도 되긴 하는데, 단순히 조건문을 추가해서 답을 구하도록 만들었다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
stair=[]
dp=[0]*300
n=int(input())
for _ in range(n):
    stair.append(int(input()))
 
if n>=3:    
    dp[0]=stair[0]
    dp[1]=max(stair[0]+stair[1],stair[1])
    dp[2]=max(stair[0]+stair[2],stair[1]+stair[2])
 
    for i in range(3,n):
        dp[i]=max(dp[i-2]+stair[i],stair[i-1]+stair[i]+dp[i-3])
 
    print(dp[n-1])
elif n==2:
    print(max(stair[0]+stair[1],stair[1]))
elif n==1:
    print(stair[0])
cs

 

문제링크:

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

 

2579번: 계단 오르기

계단 오르기 게임은 계단 아래 시작점부터 계단 꼭대기에 위치한 도착점까지 가는 게임이다. <그림 1>과 같이 각각의 계단에는 일정한 점수가 쓰여 있는데 계단을 밟으면 그 계단에 쓰여 있는 점수를 얻게 된다. 예를 들어 <그림 2>와 같이 시작점에서부터 첫 번째, 두 번째, 네 번째, 여섯 번째 계단을 밟아 도착점에 도달하면 총 점수는 10 + 20 + 25 + 20 = 75점이 된다. 계단 오르는 데는 다음과 같은 규칙이 있다. 계단은 한 번에 한 계단씩

www.acmicpc.net

 

728x90
반응형

'Algorithm > Python' 카테고리의 다른 글

[BOJ]1748. 수 이어 쓰기 1  (0) 2020.03.17
[BOJ]1267. 핸드폰 요금  (0) 2020.03.12
[BOJ]13458. 시험 감독  (0) 2020.03.05
[BOJ]6588. 골드바흐의 추측  (0) 2020.03.03
[Programmers]2019 Kakao.길 찾기 게임  (0) 2020.02.27
728x90
반응형

문제:

총 N개의 시험장이 있고, 각각의 시험장마다 응시자들이 있다. i번 시험장에 있는 응시자의 수는 Ai명이다.

감독관은 총감독관과 부감독관으로 두 종류가 있다. 총감독관은 한 방에서 감시할 수 있는 응시자의 수가 B명이고, 부감독관은 한 방에서 감시할 수 있는 응시자의 수가 C명이다.

각각의 시험장에 총감독관은 오직 1명만 있어야 하고, 부감독관은 여러 명 있어도 된다.

각 시험장마다 응시생들을 모두 감시해야 한다. 이때, 필요한 감독관 수의 최솟값을 구하는 프로그램을 작성하시오.

입력:

첫째 줄에 시험장의 개수 N(1<=N<=1,000,000)이 주어진다.

둘째 줄에는 각 시험장에 있는 응시자의 수 Ai(1<=Ai<=1,000,000)가 주어진다.

셋째 줄에는 B와 C가 주어진다.(1<=B,C<=1,000,000)

출력:

각 시험장마다 응시생을 모두 감독하기 위해 필요한 감독관의 최소 수를 출력한다.

풀이방법:

총감독관은 시험장마다 1명씩만 존재해야 하므로 answer를 시험장의 수로 초기화한다. 

그리고 각 시험장마다 총감독관이 감시할 수 있는 인원을 빼고 아직 감시해야 할 인원들이 남았다면 이를 부감독관에게 할당하도록 한다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
n=int(input())
tester=list(map(int,input().split()))
b,c=map(int,input().split())
answer=n
 
for test in tester:
    test-=b
    if test>0:
        p,r=divmod(test,c)
        if r:
            answer+=p+1
        else:
            answer+=p
 
print(answer)
cs

문제링크:

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

 

13458번: 시험 감독

첫째 줄에 시험장의 개수 N(1 ≤ N ≤ 1,000,000)이 주어진다. 둘째 줄에는 각 시험장에 있는 응시자의 수 Ai (1 ≤ Ai ≤ 1,000,000)가 주어진다. 셋째 줄에는 B와 C가 주어진다. (1 ≤ B, C ≤ 1,000,000)

www.acmicpc.net

 

728x90
반응형

'Algorithm > Python' 카테고리의 다른 글

[BOJ]1267. 핸드폰 요금  (0) 2020.03.12
[BOJ]2579. 계단 오르기  (0) 2020.03.10
[BOJ]6588. 골드바흐의 추측  (0) 2020.03.03
[Programmers]2019 Kakao.길 찾기 게임  (0) 2020.02.27
[BOJ]13305. 주유소  (0) 2020.02.25
728x90
반응형

문제:

1742년, 독일의 아마추어 수학가 크리스티안 골드바흐는 레온하르트 오일러에게 다음과 같은 추측을 제안하는 편지를 보냈다.

 

4보다 큰 모든 짝수는 두 홀수 소수의 합으로 나타낼 수 있다.

 

예를 들어 8은 3+5로 나타낼 수 있고, 3과 5는 모두 홀수인 소수이다. 또, 20 = 3 +17 = 7+13, 42 = 5+37 = 11+ 31 = 13 + 29 = 19 +23 이다.

 

이 추측은 아직도 해결되지 않은 문제이다. 백만 이하의 모든 짝수에 대해서, 이 추측을 검증하는 프로그램을 작성하시오.

입력:

입력은 하나 또는 그 이상의 테스트 케이스로 이루어져 있다. 테스트 케이스의 개수는 100,000개를 넘지 않는다.

각 테스트 케이스는 짝수 정수 n 하나로 이루어져 있다. (6 <= n <=1000000)

입력의 마지막 줄에는 0이 하나 주어진다.

출력:

각 테스트 케이스에 대해서, n = a+b 형태로 출력한다. 이때, a와 b는 홀수 소수이다. 숫자와 연산자를 공백 하나로 구분되어져 있다. 만약, n을 만들 수 있는 방법이 여러 가지라면, b-a가 가장 큰 것을 출력한다. 또, 두 홀수 소수의 합으로 n을 나타낼 수 없는 경우에는 "Goldbach's conjecture is wrong"을 출력한다.

풀이방법:

 여러 케이스에서 소수를 사용해야 하는데, 그 때마다 계산을 해야 하는 소수들을 구하면 너무 오랜 시간이 걸리기 때문에 최대 1,000,000를 넘지 않는다는 것을 이용해서 미리 소수들을 구하도록 한다. 

 따라서 소수를 효율적으로 구할 수 있는 방법 중 하나인 에라토스테네스의 체 방법을 사용해서 배열을 구한다. 그 뒤로는 입력으로 들어온 n 이하에 존재하는 소수들에 대해서 합을 구해본다. 이 때 n//2까지만 반복문을 돌아도 되는데, 그 뒤에 있는 값들은 이미 이 전에 검사했을 것이기 때문이다. (ex) 3+5=8, 5+3=8)

 그리고 두 수간의 차이가 가장 큰 경우를 출력해야 하므로 작은 수부터 즉 3부터 확인을 하며 처음으로 추측을 만족시킬 때가 간격이 가장 크기 때문에 break를 걸고 형식에 맞게 출력을 하도록 한다.

 원래는 추측이 틀렸을 때에는 지정된 문구를 출력해야 하지만, 이 추측은 실제로 존재하며 아직 반례를 찾지 못했기 때문에 틀린 경우가 없기 때문에 생략했다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def isPrime(n):
    numbers=[1]*n
    
    for i in range(2,int(n**0.5)+1):
        if numbers[i]==1:
            for j in range(i+i,n,i):
                numbers[j]=0
    return numbers
    
numbers=isPrime(1000000)
 
while True:
    n=int(input())
    if n==0:
        break
    for i in range(3,n//2+1):
        if numbers[i] and numbers[n-i]:
            print("{} = {} + {}".format(n,i,n-i))
            break
cs

문제링크:

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

 

6588번: 골드바흐의 추측

문제 1742년, 독일의 아마추어 수학가 크리스티안 골드바흐는 레온하르트 오일러에게 다음과 같은 추측을 제안하는 편지를 보냈다. 4보다 큰 모든 짝수는 두 홀수 소수의 합으로 나타낼 수 있다. 예를 들어 8은 3 + 5로 나타낼 수 있고, 3과 5는 모두 홀수인 소수이다. 또, 20 = 3 + 17 = 7 + 13, 42 = 5 + 37 = 11 + 31 = 13 + 29 = 19 + 23 이다. 이 추측은 아직도 해결되지 않은 문제이다. 백만 이하의 모

www.acmicpc.net

 

728x90
반응형

'Algorithm > Python' 카테고리의 다른 글

[BOJ]2579. 계단 오르기  (0) 2020.03.10
[BOJ]13458. 시험 감독  (0) 2020.03.05
[Programmers]2019 Kakao.길 찾기 게임  (0) 2020.02.27
[BOJ]13305. 주유소  (0) 2020.02.25
[BOJ]2485. 가로수  (0) 2020.02.20
728x90
반응형

아래 모든 내용들은 Christopher Bishop의 pattern recognition and machine learning에서 더 자세히 볼 수 있습니다.

12. 연속 잠재 변수

  • 이미 9장에서 가우시안 혼합 분포와 같은 이산 잠재 변수를 가지는 확률 모델을 살펴보았다.

    • 이제 몇몇 잠재 변수들 또는 모든 잠재 변수들이 연속적인 모델에 대해 살펴본다.
  • 이러한 모델은 원래 데이터 집합 공간의 차원보다 훨씬 더 낮은 차원의 manifold에 모든 데이터 포인트들이 가깝게 놓이는 성질을 가진다.

    • manifold란 데이터가 있는 공간이라고 생각하면 된다.
  • 예시를 살펴 보도록 한다.

    • 64 x 64 픽셀로 표현되는 숫자 이미지를 100 x 100 크기의 이미지에 삽입하도록 한다.

    • 빈 공간은 0 값을 가지게 되고, 숫자를 넣는 위치는 random이며 다음과 같이 표현된다.

    • 각 이미지는 10,000개의 픽셀을 가지게 되며, 세 개의 변동 가능한 자유도만이 존재한다.

      • 수직 이동, 수평 이동, 회전 이동
    • 각각의 데이터 포인트들은 실 데이터 공간의 부분 공간상에 존재, 이 부분 공간을 intrinsic dimensionality라고 한다.

  • 위의 예시의 경우 manifold는 비선형이다. 하나의 숫자를 이동시켰을 때 특정 픽셀은 0에서 1로, 다시 0으로 바뀌는 비선형 이기 때문이다.

  • 또한 이동과 회전 매개변수는 잠재 변수들이다.

    • 우리가 관측하게 되는 것은 이미지 벡터인데 생성될 때 이동 변수나 회전 변수들이 사용되었는지 알 수 없다.
  • 가장 단순한 연속 잠재 변수 모델에서는 잠재 변수와 관측 변수가 둘 다 가우시안 분포를 이룬다고 가정하고 잠재 변수들의 상태에 대한 관측 변수들의 선형 가우시안 종속성을 사용한다.

    • 이를 통해 PCA를 도출한다.

12.1 PCA

PCA는 차원수 감소, 손실 허용 데이터 압축, 특징 추출, 데이터 시각화 등의 여러 분야에서 사용되고 있다.

  • PCA에는 두 가지 정의가 있지만 결과적으로는 같은 알고리즘을 도출하게 된다.
    • 데이터를 주 부분 공간(prinipal subspace)이라고 하는 더 낮은 선형 공간에 직교 투영하는 과정이며 위 그림과 같이 진행된다.
      • 이때 투영 과정은 투영된 데이터의 분산이 최대화되는 방향으로 이루어져야 한다.
    • 평균 투영 비용을 최소화하는 선형 투영으로 PCA를 정의
      • 이 경우 평균 투영 비용은 데이터 포인트와 그 투영체 간의 평균 제곱 거리로 정의

12.1.1 최대 분산 공식화

  • 관측 데이터 집합 xn이 있다고 하자. 이는 차원수 D를 가지는 유클리드 변수다. 우리의 목표는 데이터를 M < D의 차원수를 가지는 공간상에 투영하는 것이다.
    • 이때 투영된 데이터의 분산이 최대가 되도록 한다.
    • M값이 주어졌다고 가정하고, 나중에 적절한 M 값을 찾아내는 것을 알아본다.
  • M = 1이라고 하자.
  • 이 공간의 방향을 D차원 벡터 u1로 정의할 수 있다. 편의를 위해서 단위 벡터를 사용한다.
    • 즉 u1Tu1 = 1 이다.
      • u1에 의해 정의되는 방향이므로 임의의 크기를 자기는 벡터를 사용해도 일반성을 잃지 않는다.
  • 각각의 데이터 포인트는 u1Txn에 투영된다.

  • 그리고 투영된 데이터 분산은 다음처럼 주어진다.

  • S는 데이터 공분산 행렬로서 다음처럼 주어진다.

  • 이제 투영된 분산을 u1에 대해서 극대화하도록 한다. 이 때 이 값이 무한대로 발산하는 것을 막기 위해 제약 조건을 걸어야 하며 정규화 조건으로부터 제약 조건을 얻고 라그랑주 승수법을 도입해 최대화를 실시하도록 한다.

  • u1에 대한 미분을 0으로 설정하면 다음과 같다.

    • 즉 u1이 S의 고유 벡터가 된다. 왼쪽에 u1T를 곱하면 분산은 다음과 같이 주어진다.

    • u1를 가장 큰 고윳값 λ1을 가지는 고유 벡터로 설정하면 최대의 분산을 가지게 되고, 이 고유 벡터를 제1주성분이라고 한다.

  • 요약하면, PCA는 데이터 집합의 평균과 공분산 행렬 S를 계산하고 S의 가장 큰 M개의 고윳값들에 해당하는 M개의 고유 벡터들을 찾는 과정

12.1.2 최소 오류 공식화

  • 투영 오류를 최소화하는 방식을 살펴본다.

  • 완전히 정규 직교하는 D차원의 기저 벡터들 ui을 도입해 보자.

    • uiTuj = δij를 만족한다.
  • 이 기저들은 완전하므로, 데이터 포인트들을 기저 벡터들의 선형 결합으로 정확하게 표현할 수 있다.

    • 계수 ani는 각 데이터 포인트마다 다른 값이며, 새 시스템으로 좌표계를 회전 변환하는 것에 해당한다.

    • uj와 내적을 진행한 후 정규 직교 성질을 이용하면 anj=xnTuj를 얻는다.

  • 목표는 이 데이터 포인트들을 제한된 수 M < D개의 변수들을 이용해서 근사하는 것

    • 저차원 부분 공간으로의 투영에 해당
  • M개의 기저 벡터들을 이용해 M차원 선형 부분 공간 표현할 수 있고, xn을 다음과 같이 근사한다.

  • zni는 특정 데이터 포인트에 대해 종속적이지만 bi는 모든 데이터 포인트들에 대해 동일한 상수다.

    • 이러한 값들은 차원을 줄임으로 인해 발생하는 왜곡도를 감소시키는 방향으로 자유롭게 선택할 수 있다.
  • 왜곡도를 측정하고 이를 최소화하도록 한다. 왜곡도는 다음과 같다.

    • 우선 각각의 zni 값에 대한 최소화를 고려해 보자. x_tilda 값을 치환하고, znj에 대한 미분값을 0으로 설정한 후 정규직교 조건을 사용하면 다음을 구할 수 있다.

      • 여기서 j = 1, ... ,M이다.
      • 12.10 식에서 앞 부분에 해당하는 것을 의미한다.
    • bi에 대한 미분값을 0으로 놓고 정규직교 조건을 이용하면 다음을 얻을 수 있다.

      • 여기서 j = M+1, ... , D다.
      • 12.10 식에서 뒷 부분에 해당하는 것을 의미한다.
  • 여기서 zni와 식 12.10의 bi를 대입해 넣고 식 12.9의 일반 전개식을 사용하면 다음과 같다.

  • 이로부터 xn에서 x_tilda로의 이동 벡터는 주 부분 공간에 직교하는 공간상에 존재함을 알 수 있다.

    • 이동 벡터들은 i = M+1 , ... , D에 대한 {ui}의 선형 결합이기 때문
    • 투영된 포인트는 x_tilda 부분 공간상에 놓여 있어야 하지만, 공간 내에서는 자유롭게 이동시킬 수 있으므로 최소 오류를 달성 할 수 있다.
  • 따라서 J를 {ui}의 함수로 표현한다.

  • 이제 {ui}에 대해 최소화한다.

    • 이는 제약 조건이 있는 최소화이다. 따라서 라그랑주 승수법을 사용한다.
    • 제약 조건은 정규직교 조건으로부터 기인한다.
  • 이차원 데이터 공간 D = 2, 주 부분 공간 M = 1의 예시로 살펴본다.

    • J=u2TSu2를 최소화하는 방향 u2를 선택해야 하고, 제약 조건u2Tu2=1을 만족해야 한다.

    • u2에 대한 미분값을 0으로 설정하면 Su2 = λ2u2를 얻는다. u2는 S의 고유 벡터가 된다.

    • u2에 대한 해를 왜곡도 식에 역으로 대입해 넣으면 J=λ2가 된다.

      • 두 개의 고윳값들 중 작은 고윳값에 해당하는 고유 벡터로 u2를 선택해 J를 최소로 만들 수 있다.
  • 이 내용은 제곱 투영 거리의 평균값을 최소화하기 위해 주성분 부분 공간이 데이터 포인트들의 평균을 통과하도록 해 최대 분산의 방향과 정렬되도록 한다.

  • 따라서 이를 일반화하면 다음과 같다.

  • 지금까지는 M < D인 경우만 고려하였는데, M=D인 경우에도 유효하다.

    • 이 경우엔 차원 감소는 없으며, 좌표축들을 회전시켜 주성분들에 정렬되도록 한다.
728x90
반응형

+ Recent posts