코테/백준

[백준/JAVA] 16987번: 계란으로 계란치기

imname1am 2023. 9. 6. 23:58
반응형

🔺 문제

 

16987번: 계란으로 계란치기

원래 프로그래머의 기본 소양은 팔굽혀펴기를 단 한 개도 할 수 없는 것이라고 하지만 인범이는 3대 500을 넘기는 몇 안되는 프로그래머 중 한 명이다. 인범이는 BOJ에서 틀린 제출을 할 때마다 턱

www.acmicpc.net

 

 

🔺 코드

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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import java.util.*;
import java.io.*;
 
public class Main {
    static int N, max = Integer.MIN_VALUE;
    static int[] durability, weight;
    
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        
        N = Integer.parseInt(br.readLine());
        
        durability = new int[N];    // 내구성 배열
        weight = new int[N];        // 무게 배열
        
        for(int i = 0 ; i < N ; i++) {
            st = new StringTokenizer(br.readLine(), " ");
            
            durability[i] = Integer.parseInt(st.nextToken());
            weight[i] = Integer.parseInt(st.nextToken());
        }
        
        back(0);
        System.out.println(max);
    }
    
    private static void back(int depth) {
        // 마지막 계란인 경우
        if(depth == N) {
            int cnt = 0;
            
            for(int i = 0 ; i < N ; i++
                if(durability[i] <= 0)  // 깨진 계란 개수 구하기
                    cnt++;
            
            max = Math.max(max, cnt);
            return;
        }
        
        // 내구성이 0 이하면, 다음으로 넘어가기
        if(durability[depth] <= 0)
            back(depth + 1);
        else {
            boolean broken = false// 깰 계란 있는지 확인용 변수
            
            for(int i = 0 ; i < N ; i++) {
                if(i == depth || durability[i] <= 0)    // 같은 계란이거나 내구성이 0 이하인 경우, 깰수 X
                    continue;
                
                broken = true;  // 깰 계란 존재
                
                // 두 계란 내구성 감소
                durability[i] -= weight[depth];
                durability[depth] -= weight[i];
                
                back(depth + 1);
                
                // 다음 경우의 수 위해 원상복구
                durability[i] += weight[depth];
                durability[depth] += weight[i];
            }
            
            // 깰 계란이 없으면, 다음으로 넘어가기
            if(!broken)
                back(depth + 1);
        }
    }
}
cs
✅ 해결 아이디어
✔ 백트래킹 & 브루트포스
- for문 안에서 연산을 하고, 조건에 맞춰 재귀호출

 


🔺 다른 풀이들

max를 구하는 방법이 약간 다르다.

 

백준 16987 - 계란으로 계란치기

[문제 바로가기] 1. 유형 브루트포스 DFS 백트래킹 2. 풀이 DFS를 쓰는 문제였습니다. 처음에 한글 이해하는게 조금 힘들었습니다. 2-1. 설계 2-2. 코드 풀이 3. 코드 import java.io.*; import java.util.*; public c

moons-memo.tistory.com

 


💬 느낀 점

기본은 브루트포스를 잘 하고 조건문을 빠뜨리지 않고 쓰는 것 같다.

조합/순열 구하는 단순 백트래킹 문제는 풀겠는데

이렇게 조금이라도 조건을 더하면 못 풀다니...

 

다음 복습 때는 혼자 힘으로 풀고 싶다!

 

 

1회독 2회독 3회독 4회독 5회독
V 240601      

 

 

(+240601 2회독 : 15676KB, 188ms)

개인적으로 이 풀이가 더 깔끔하니 좋은 것 같당.

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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import java.util.*;
import java.io.*;
 
public class Main {
    static int N, answer;
    static int[] S,W;
    
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        
        N = Integer.parseInt(br.readLine());
        
        S = new int[N]; // 계란 내구도
        W = new int[N]; // 계란 무게
        
        for(int i = 0 ; i < N ; i++) {
            st = new StringTokenizer(br.readLine(), " ");
            S[i] = Integer.parseInt(st.nextToken());
            W[i] = Integer.parseInt(st.nextToken());
        }
        
        dfs(00);  // 0번째 계란부터 시작, 깨진 계란 수
        System.out.println(answer); // 깰 수 있는 최대 몇 개의 계란
    }
    
    private static void dfs(int depth, int cnt) {   // cnt: 깨진 계란 수
        // 마지막 계란까지 다 들었으면 종료
        if(depth == N) {
            answer = Math.max(answer, cnt);
            return;
        }
        
        // 손으로 든 계란이 이미 깨졌거나, 모든 계란이 이미 다 꺠진 경우 > 다음 계란 들기
        if(S[depth] <= 0 || cnt == N-1) {
            dfs(depth + 1, cnt);
            return;
        }
        
        int tmpCnt = cnt;   // 깨진 계란 수 원상복구 위해 저장용
        
        for(int i = 0 ; i < N ; i++) {
            // 손으로 들고 있는 계란 = 부딪히려고 하는 계란인 경우, 계란이 이미 깨져있는 경우 통과
            if(i == depth || S[i] <= 0continue;
            
            // 계란 부딪히기
            S[i] -= W[depth];
            S[depth] -= W[i];
            
            if(S[depth] <= 0)   cnt++;  // 손에 든 계란이 깨지면 +1
            if(S[i] <= 0)       cnt++;  // 타겟이 된 계란이 깨지면 +1
            
            dfs(depth + 1, cnt);    // 다음 계란 들기
            
            // 원상복구
            S[i] += W[depth];
            S[depth] += W[i];
            cnt = tmpCnt;
        }
    }
}
 
cs


(참고)

 

[백준_16987번] 계란으로 계란치기

https://www.acmicpc.net/problem/16987 16987번: 계란으로 계란치기 원래 프로그래머의 기본 소양은 팔굽혀펴기를 단 한 개도 할 수 없는 것이라고 하지만 인범이는 3대 500을 넘기는 몇 안되는 프로그래머

subin-programming.tistory.com

 

[백준] 16987: 계란으로 계란치기 (Java)

BOJ 16987: 계란으로 계란치기 https://www.acmicpc.net/problem/16987계란을 깨는데 조건계란에는 내구도(dura)와 무게(weight)가 있다.계란을 계란끼리 치면 계란의 내구도(dura)는 다른 계란의 무게(weight)만큼

velog.io

 

반응형