(C++) 백준 16987 계란으로 계란치기

mnaz·2021년 12월 8일

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

주어지는 개수가 많지 않아서 브루트포스로 모든 경우를 따져본다고 생각했다
그래서 재귀로 풀었다
무조건 오른쪽에 있는 계란으로 쳐야하므로 dfs로 생각하고 푼 사람도 있었는데 나는 고건 생각 못했다

문제는 생각보다 간단했는데 두가지 예외처리때문에 틀렸다

1. 예외처리에 대해 return하지 않음.

오른쪽에 있는 계란이 이미 깨져있으면 그 다음 계란으로 넘어가야 한다. if(isBreak[x]) BreakEgg(x+1)
그런데 여기서 return하지 않았더니 그 다음 라인이 계속 실행되서 답이 달라지는 경우가 있었다~ 예외처리에 대해 return 필수

2. 더이상 깰 계란이 없는 경우를 예외처리하지 않음.

먼저 짠 코드는 3개의 계란이 있고 1, 3번이 깨졌을 경우 2번 계란에서 넘어가지 않아 실행이 종료되었다.
따라서 더이상 깰 계란이 없는 경우를 확인하기 위한 변수(flag)를 사용하여 예외처리 해주었다.


stream> 
#include <algorithm>
using namespace std;


int N;
int durability[10];
int weight[10];
int ans;
bool isBreak[10];

void BreakEgg(int x) { 

    if(x==N) {
        int cnt=0;
        for(int i=0; i<N; i++) if(isBreak[i]) cnt++;
        ans= max(cnt, ans);

        return ;
    }
    if(isBreak[x]) {
        BreakEgg(x+1);
        return ; // return 처리 안해주면 isBreak[x] = true인 경우에도
        // 게속 실행되서 에러 발생.
    }

    bool flag=false;
    for(int i=0; i<N; i++) {
         if(i==x || isBreak[i]) continue;

         flag=true;
         durability[i]-=weight[x];
         durability[x]-=weight[i];
         if(durability[i]<=0) isBreak[i]=true;
         if(durability[x]<=0) isBreak[x]=true;

         BreakEgg(x+1);

         isBreak[x]=false;
         isBreak[i]=false;
         durability[i]+=weight[x];
         durability[x]+=weight[i];
    }

    if(!flag){
        BreakEgg(N);
    }


}

int main() {

    cin>>N;

    for(int i=0; i<N; i++) {
        cin>>durability[i]>>weight[i];
    }

    BreakEgg(0);
    cout<<ans;


}






0개의 댓글