ch3-1-완전탐색-그냥다해보기
가능한 모든 경우의 수를 만들어보고 탐색
가능한 모든 경우의 수를 알아야 함
brute force 라고도 부름
BFS
재귀
비트마스크
순열
백트래킹
기법을 주로 사용하여 풀 수 있음
풀어보기
날짜 계산 - 1476
E, S, M 이라는 연도를 사용하는 나라가 있음
E: 1~15, S: 1~28, M: 1~19
각 연도 값이 주어졌을 때, 현재 사용하는 년도 구하기
경우의 수 먼저 구해서 brute force 로 할 수 있는지 알아보기
E, S, M 은
15*28*19 = 7980
정도 됨. 0~7980 까지 모든 경우의 수를 따져봐도 부담없음
int x, y, z, a, b, c;
cin>>x>>y>>z;
for(int i = 0; ; i+=1) {
if(a == x && b == y && c == z) {
cout<<i<<endl;
break;
}
a += 1;
b += 1;
c += 1;
if(a > 15) a = 1;
if(b > 28) b = 1;
if(c > 19) c = 1;
}
리모컨 1107
버튼이 0~9, +, -가 있음
일부 숫자 버튼 망가짐
초기 채널은 100
이동하려는 채널이 N 일 경우 버튼 누르는 최소 횟수 구하기
bruteforce 느낌남. 모든 경우의수를 먼저 알아보자
채널의 개수가 0~500,000. 1 억개보단 훨씬 적음
이동할 수 있는 방법은 다음과 같다.
100 번 채널에서 +/-로 이동하기
목적지까지 +/- 누르기.
숫자버튼으로 채널 이동하기
숫자버튼으로 채널 이동 (모든 경우의수를 여기서 따질거다)
목적지까지 +/- 누르기.
2 번에서 숫자버튼으로 이동할 경우, 버튼 고장 여부를 따져야한다.
각 자리수별로 검사
int possibleNumBtn(int num) {
// num이 0일 경우, 아래 while문에서 0은 검사하지 못하기 때문에 예외처리.
if(num == 0) {
if(broken[0]) {
return 0;
} else {
return 1;
}
}
int len = 0; // 여기서 직접 버튼 개수만큼 +를 해줘서, 고장나지 않았을 경우 버튼 개수만큼 리턴
while(num > 0) {
if(broken[num % 10]) {
return 0;
}
len += 1;
// 1의자리부터 각 자리수별로 검사하기 위해 10으로 나눠준다.
num /= 10;
}
return len;
}
for(int i = 0; i < 1000000; i+=1) {
int len = possibleNumBtn(i);
if(len > 0) {
int oneBtn = target - i;
if(oneBtn < 0) {
oneBtn = -oneBtn;
}
if(ans > oneBtn + len) {
ans = oneBtn + len;
}
}
}
이동하려는 목적지 N 은 0~500,000 까지지만, 채널은 무한대 만큼이다.
그래서, 500000 을 이동할 경우
4,9 가 고장 날 경우
1~500000 까지 이동할 수 있다고 했을 때, 48X,XXX 에서 이동하는게 최소횟수임.
하지만 500000 이상일 경우 500001 에서 -1 로 이동하는게 이득.
for 문이 백만인 이유는 50 만이 최대 목적지라고 할 때, 0~50 만~100 만 각 50 만 차이로 경우의 수를 구하면 모두 커버 가능하기 떄문이다.
Summary
브루트 포스 문제같을 때는 경우의수를 따져서, 1억 이하인 경우 모든 경우의수를 구한다
모든 경우의 수 중
최소값
최대값
해답
등 을 찾는다.
Last updated
Was this helpful?