포스트

백준 1535. 안녕

안녕

DFS 대표 문제 퇴사와 유사한 문제

1. 간단 설명


image

N명의 사람이 방문안을 왔다

인사를 하면 체력을 잃는다

체력을 잃는 대신 기쁨을 얻는다

체력이 허락하는 한 인사를 하고 얻을 수 있는 최대 기쁨을 출력하는 문제

2. 예시


1
2
3
3명의 방문객
잃는 체력 : 1 21 79
얻는 기쁨 : 20 30 25

시작 체력은 100이므로

(1), (21), (79), (1,21), (1,79), (21,79), (1, 21, 79)로 각각 시도해본다

체력이 0이거나 음수로 떨어지면 불가능하므로 (21,79), (1, 21, 79) 는 불가능하므로

(1, 21)일때 얻을 수 있는 기쁨이 50으로 가장 크다

3. 알고리즘


처음 생각한 알고리즘

1
2
3
4
5
6
7
8
9
1. N, damage, price를 입력받는다
2. 1명만 볼 경우, 2명 볼 경우, ... , N명 볼 경우를 DFS 돌려본다
3. DFS(지금 몇명본건지, 몇명 볼건지, 남은 체력, 얻은 기쁨)
	3-1. 만약 남은 체력이 0이하라면 리턴
	3-2. 모든 사람을 봤다면, 현재 얻은 기쁨과 기록된 최대 기쁨을 비교 후 리턴
	3-3. i~N 사이에서 다음 값을 뽑는다
		3-3-1. 만약 이미 뽑은 사람이라면 패스한다
		3-3-2. 아니라면, 이 사람을 뽑아서 DFS를 재호출한다
		DFS(뽑은사람 수 + 1, 몇명 볼건지, 남은체력 - 이사람이 주는 체력피해, 현재 얻은 기쁨 + 이사람이 주는 기쁨)

이 방법은 10명까지 정도는 가능한데, 12명을 넘는 케이스에서는 시간초과가 발생했다

1명 뽑는경우, 2명 뽑는경우, … 12명 뽑는경우를 모두 체크해야하므로 시간초과 발생

DP로 처리할수도 있겠지만 더 좋은 방법이 있으므로 이 방법으로 시도함

1
2
3
4
5
6
7
DFS(int level, int max_level, int hp, int sum){
	1. 체력이 0 이하로 떨어지면 리턴
	2. 다 뽑았으면 결과값 비교 후 갱신, 이후 리턴
	3. 현재 레벨의 사람을 뽑을것인지 말것인지를 DFS로 결정
		DFS(level + 1, hp, sum) 안만나는 
		DFS(level + 1, hp - damage[level], sum + price[level) 만나는 경우
}

첫번째 사람부터 이사람을 만날지 만나지 않을지로 접근하는 것

N명을 세워놓고 1번부터 N번까지 이사람을 만날지 안만날지 선택하면서 DFS를 돌린다

필요 변수

  • 사람 수 int N (1 ≤ N ≤21)
  • int damage[21], int price[21] 이사람이 주는 데미지와 기쁨 (0≤ 체력, 기쁨 ≤ 100)
  • 최대 기쁨 int max_res
    • 20명이 100의 기쁨을 줘도 int 내에서 처리 가능

4. 소스코드


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
34
35
36
37
38
39
40
41
42
43
#include <iostream>

#define MAX 21

using namespace std;

int N;
int damage[MAX], price[MAX];
int max_res = 0;

void Input() {
	freopen_s(new FILE*, "input.txt", "r", stdin);
	cin >> N;
	for (int i = 0; i < N; i++) {
		cin >> damage[i];
	}
	for (int i = 0; i < N; i++) {
		cin >> price[i];
	}

}

void DFS(int level, int hp, int sum) {
	if (hp <= 0) return;
	if (level == N) {
		if (sum > max_res) {
			max_res = sum;
		}
		return;
	}
	DFS(level + 1, hp - damage[level], sum + price[level]);
	DFS(level + 1, hp, sum);
}

int main() {
	Input();

	DFS(0, 100, 0);

	cout << max_res;

	return 0;
}
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.