본문 바로가기

Notice
Recent Posts
Recent Comments
«   2024/05   »
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
Tags
더보기
Archives
관리 메뉴

1309.동물원 본문

알고리즘 문제풀기/백준(Acmicpc)

1309.동물원

알광(Algwang) 2019. 1. 22. 09:21

문제링크 : https://www.acmicpc.net/problem/1309


<입력>


우리의 크기 N(1<=N<=100,000)


<출력>


사자를 배치하는 경우의 수를 9901로 나눈 나머지


<풀이>


2xN 타일링과 같은 전형적인 dp문제이다.


이런 방식의 문제는 부분 문제로 나누어 점화식을 세워야 한다.


사자는 가로 세로로 인접할 수 없다.


즉, 세로 3번 칸에 있는 사자는 4번 칸에는 영향을 주지만 5번 칸에는 주지 못한다.


N-2 칸을 채우는 방법은 N번째 칸에 어떤 값이 들어오던지 영향을 받지 않는다.


따라서 N번째 칸을 왼쪽에 사자를 놨을 때 / 오른쪽에 사자를 놨을 때 / 놓지 않았을 때로 나누어


a(N-2) * 3이 우선적으로 포함됨을 알 수 있다.


다음으로 N-1 칸을 채우는 방법을 생각해야 한다.


우선 N-2칸을 이미 모두 고려했기 때문에 a(N-1) - a(N-2)를 해준다.


(이 때, 9901로 나눈 나머지이므로 a(N-1)이 더 작아질 수 있으므로 예외처리 해줘야 한다.)


그럼 전과 마찬가지로 N-1번째 칸의 왼쪽이 차있을 경우 / 오른쪽이 차있을 경우로 나누었을 때


N번째 칸이 N-1번째 칸의 반대쪽에 있거나 / 비어있거나 2가지 경우가 존재하므로


(a(N-1) - a(N-2)) * 2이 마지막으로 포함된다.


따라서 위와 같은 점화식이 만들어진다.


이를 풀어서 a(N-1)*2 + a(N-2)로 만들 경우 a(N-1)이 a(N-2)보다 커지는 경우를 예외처리할 필요가 없어진다.


이 방법을 통해 9901로 나누는 경우를 더 쉽게 구할 수도 있다.




- 소스 코드 -


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include<iostream>
 
using namespace std;
 
typedef long long ll;
 
int main(void){
    ll arr[100001]={0};
    arr[0]=3;
    arr[1]=7;
    int N;
    cin>>N;
    for(int i=2;i<=N;i++){
        if(arr[i-1]<=arr[i-2]){
            arr[i]=0LL+((arr[i-2]*3)+((arr[i-1]+9901-arr[i-2])*2))%9901;  
        }else{
            arr[i]=0LL+((arr[i-2]*3)+((arr[i-1]-arr[i-2])*2))%9901;  
        }
        
    }
    cout<<arr[N-1]<<endl;
}
 
cs





'알고리즘 문제풀기 > 백준(Acmicpc)' 카테고리의 다른 글

2870. 수학숙제  (0) 2019.01.25
1431.시리얼 번호  (0) 2019.01.24
11060. 점프 점프  (0) 2019.01.18
10164. 격자상의 경로  (0) 2019.01.17
14720. 우유 축제  (0) 2019.01.15
Comments