Notice
Recent Posts
Recent Comments
Link
«   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
Archives
Today
Total
관리 메뉴

풀이 보관함

[C++] 백준 16987번: 계란으로 계란치기 본문

problem solving/백준

[C++] 백준 16987번: 계란으로 계란치기

viin 2023. 2. 28. 18:52

🔗 문제

16987번: 계란으로 계란치기

 

16987번: 계란으로 계란치기

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

www.acmicpc.net

 

🖍 풀이

 

문제 정리

내구도와 무게를 가진 계란 N개가 있다.

왼쪽부터 깨지지 않은 계란을 집어들고 다른 안 깨진 계란을 깰 시도를 한다.

이 때! 내가 깨질 수도 있고 다른 계란이 깨질 수도 있다.

  • 두 계란의 내구도는 상대 계란의 무게만큼 감소한다.
  • 내구도가 음수가 되면 그 계란이 깨진다.

이걸 깰 계란이 없을 때까지 반복한다.

 

깰 수 있는 계란이 여러 개 있을 때 탐욕 기법을 이용해서 풀어야 하나 고민을 했지만! 어떤 계란을 깨는지에 따라 다음 계란이 깰 수 있는 대상이 달라지기때문에 DFS를 이용한 완전 탐색으로 풀어주었다.

 

 

💾  소스

#include <iostream>

int N, answer = 0;
bool crack[20] = {false, };
int S[20]; int W[20];

bool flag = false;
void DFS(int pick, int sum)
{
    answer = (answer > sum ? answer : sum); // 지금까지 깬 최대 계란 수 확인
    
    // 내가 들고 있는 계란이 깨진거라면 다음 계란 들자.
    for(; pick<N; ++pick)
    {
        if(crack[pick] == false)
            break;
    }
    
    if(pick >= N)
    {
        return;
    }
    
    for(int i=0; i<N; ++i)
    {
        if(i == pick || crack[i]) continue;
        
        S[i] -= W[pick];
        S[pick] -= W[i];
        
        if(S[i] <= 0) crack[i] = true;
        if(S[pick] <= 0) crack[pick] = true;
        
        DFS(pick+1, sum + crack[pick] + crack[i]);
        
        S[i] += W[pick];
        S[pick] += W[i];
        
        if(S[i] > 0) crack[i] = false;
        if(S[pick] > 0) crack[pick] = false;
    }
}

int main()
{
    
    std::cin >> N;
    for(int i=0; i<N; ++i)
    {
        std::cin >> S[i] >> W[i];
    }
    
    DFS(0, 0);
    
    std::cout << answer;
    return 0;
}