kil_alpaca
기록하는 습관
kil_alpaca
전체 방문자
오늘
어제
  • 분류 전체보기 (117)
    • 잡다한 오류 (2)
    • 머신러닝 & 딥러닝 (4)
      • 이론 (2)
      • 통계 기법 (2)
      • 잡다한 오류 (0)
    • Pytorch (6)
    • Tensorflow 2 (1)
      • 오류 처리 등등 (1)
    • Ubuntu (3)
      • 이것저것 (2)
      • 오류 처리 등등 (1)
    • Problem Solving (93)
      • Dynamic Programming (52)
      • Convex Hull Trick (8)
      • Dijkstra (33)
    • 자료구조 (3)
      • 기본 자료구조 (2)
      • Tree (1)
    • 알고리즘 (5)
      • 기하학 (4)
      • 최적화 기법 (1)

블로그 메뉴

  • 홈

공지사항

인기 글

태그

  • Tensor
  • Li Chao Tree
  • Convex Hull Trick
  • convex hull
  • 딥러닝
  • 백준
  • 데이크스트라
  • 다익스트라
  • Convex Hull Optimization
  • pyTorch
  • kaiming 초기화
  • 머신러닝
  • glorot 초기화
  • 자료구조
  • 통계
  • dynamic programming
  • 텐서
  • DP
  • 통계기법
  • CCW
  • 그래프 이론
  • 그래프 탐색
  • 파이토치
  • 기하학
  • DP optimization
  • convolution layer
  • CHT
  • Dijkstra
  • 알고리즘
  • he 초기화

최근 글

티스토리

hELLO · Designed By 정상우.
kil_alpaca

기록하는 습관

Problem Solving/Dynamic Programming

[백준] 5546번: 파스타

2023. 2. 18. 10:25

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

 

5546번: 파스타

상근이는 매일 저녁으로 파스타를 만들어 먹는다. 상근이가 만들 수 있는 파스타는 총 세 종류로 토마토 소스, 크림 소스, 바질 소스이다. 상근이는 앞으로 N일 동안 먹을 파스타를 계획하려고

www.acmicpc.net


이전 기록을 토대로 현재 경우의 수를 갱신하는 dp 문제다.

 

1. 문제 조건

1) 1 ~ N 일 동안 파스타를 먹을 수 있는 방법의 가짓수를 출력한다.

2) 파스타는 토마토, 크림, 바질이 있다.

3) 3일 연속 같은 파스타를 먹을 수 없다.

4) N일 중 K일에는 그 날 먹을 파스타가 정해져 있다.

 

2. dp 배열 정의

3일 연속 같은 파스타를 먹지 못하니까,

처음에는 전 날과 전전 날에 먹은 파스타를 기록하려고 했다.

그러다보니 날짜와 현재 파스타까지 고려해야해서 4차원 dp 배열을 사용해야 했다.

 

이건 좀 아니다 싶어서 생각을 해보니,

그냥 연속으로 같은 파스타를 먹었는지 여부만 판단하면 될 것 같았다.

즉, 전 날에 전전 날과 다른 파스타를 먹었다면, 전 날에 먹은 파스타만 기억하면 된다.

 

전 날과 전전 날에 먹은 파스타의 종류에 따라 2차원 dp 배열을 정의하기로 한다.

#define MAXN 101
#define MAXK 101

#define NOT 0	// 먹을 파스타를 정하지 않음
#define T   1	// 전 날에 토마토
#define C   2	// 전 날에 크림
#define B   3	// 전 날에 바질
#define TT  4	// 전 날과 전전 날에 토마토
#define CC  5	// 전 날과 전전 날에 크림
#define BB  6	// 전 날과 전전 날에 바질

#define MAXP 7	// 파스타 조합의 개수

// dp[n][p] = n일차에 p조합으로 먹었을 때의 경우의 수
int dp[MAXN][MAXP];

// pasta[k] = k일에 먹을 파스타의 종류 (1, 2, 3)
int pasta[MAXK];

 

3. 해결법

k일에 먹을 파스타는 pasta[k] 에 저장해서 사용하기로 한다.

 

1) n = 1 (base)

- 1일차에 먹을 파스타가 미리 정해질 수도 있다.

- 따라서 pasta[1] = NOT 인지 여부를 확인해서 dp[1][?] 값을 초기화한다.

- 정해져 있다면 그 파스타만 1로, 아니라면 모든 파스타를 1로 한다. 물론 T, C, B 만 초기화해야 한다.

 

2) n > 1

- 매번 pasta[n] = NOT 인지 여부를 확인한다.

- 마음에 들진 않지만, 편하게 일일이 경우를 확인해서 dp[n][?] 의 값을 갱신시켜야 한다.

- 토마토, 크림, 바질에 대해, 연속으로 먹었을 때와 연속으로 먹지 않았을 때의 값을 각각 갱신한다.

- 전체 풀이 코드를 보면 이해하기 쉽다.

 

그리 어려운 문제는 아니라 설명은 짧게 하려 한다.


전체 풀이 코드는 다음과 같다.

#include <iostream>
using namespace std;

#define MAXN 101
#define MAXK 101
#define DIVIDER 10000

#define NOT 0
#define T   1
#define C   2
#define B   3
#define TT  4
#define CC  5
#define BB  6

#define MAXP 7

int dp[MAXN][MAXP];
int pasta[MAXK];

int main() {
	ios::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);

	int N, K; cin >> N >> K;
	while(K--) {
		int a, b; cin >> a >> b;
		pasta[a] = b;
	}

	if(pasta[1] == NOT) dp[1][T] = dp[1][C] = dp[1][B] = 1;
	else				dp[1][pasta[1]] = 1;

	for(int n=2; n<=N; n++) {
		if(pasta[n] == NOT) {
			dp[n][T] = (dp[n-1][C] + dp[n-1][B] +
						dp[n-1][CC] + dp[n-1][BB]) % DIVIDER;
			dp[n][TT] = dp[n-1][T];

			dp[n][C] = (dp[n-1][T] + dp[n-1][B] +
						dp[n-1][TT] + dp[n-1][BB]) % DIVIDER;
			dp[n][CC] = dp[n-1][C];

			dp[n][B] = (dp[n-1][T] + dp[n-1][C] +
						dp[n-1][TT] + dp[n-1][CC]) % DIVIDER;
			dp[n][BB] = dp[n-1][B];
		}
		else if(pasta[n] == T) {
			dp[n][T] = (dp[n-1][C] + dp[n-1][B] +
						dp[n-1][CC] + dp[n-1][BB]) % DIVIDER;
			dp[n][TT] = dp[n-1][T];
		}
		else if(pasta[n] == C) {
			dp[n][C] = (dp[n-1][T] + dp[n-1][B] +
						dp[n-1][TT] + dp[n-1][BB]) % DIVIDER;
			dp[n][CC] = dp[n-1][C];
		}
		else {
			dp[n][B] = (dp[n-1][T] + dp[n-1][C] +
						dp[n-1][TT] + dp[n-1][CC]) % DIVIDER;
			dp[n][BB] = dp[n-1][B];
		}
	}

	int ans = 0;
	for(int p=1; p<MAXP; p++) ans += dp[N][p];

	cout << (ans % DIVIDER) << '\n';

	return 0;
}

 

저작자표시 비영리 변경금지 (새창열림)

'Problem Solving > Dynamic Programming' 카테고리의 다른 글

[백준] 14846번: 직사각형과 쿼리  (0) 2023.02.18
[백준] 2073번: 수도배관공사  (0) 2023.02.18
[백준] 2411번: 아이템 먹기  (0) 2023.02.18
[백준] 17208번: 카우버거 알바생  (0) 2023.02.18
[백준] 17130번: 토끼가 정보섬에 올라온 이유  (0) 2023.02.17
    'Problem Solving/Dynamic Programming' 카테고리의 다른 글
    • [백준] 14846번: 직사각형과 쿼리
    • [백준] 2073번: 수도배관공사
    • [백준] 2411번: 아이템 먹기
    • [백준] 17208번: 카우버거 알바생
    kil_alpaca
    kil_alpaca

    티스토리툴바