포스트

백준 1535. 안녕

백준 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 라이센스를 따릅니다.