2018. 6. 6. 00:04ㆍ알고리즘
1783번: 병든 나이트
첫째 줄에 체스판의 세로 길이 N와 가로 길이 M이 주어진다. N과 M은 2,000,000,000보다 작거나 같은 자연수이다.
www.acmicpc.net
이 문제는 그리디 문제인데, 왜 그리디 문제인지 잘 모르겠다는 사람도 있을 것 같습니다.
이런 유형의 그리디 문제의 해법은 가능한 경우의 수를 제한을 줘서 따질 수 있다는 것입니다.
일단 이동할 수 있는 방식이 (+2, +1), (+2, -1), (+1, +2), (+1, -2) 이렇게 4개로 제한되어 있고, 이동 횟수가 4가 넘어가게 될 때는 이 4가지 방식이 모두 사용되어야 합니다.
그림을 그려가며 생각하면 더 쉽게 이해할 수 있습니다.
1 x 1 칸이 있을 때라면 답은 1이다.
1 x n 칸이 있더라도 답은 1이다.
이런 식으로 생각하게 되면 생각보다 쉽게 풀 수 있는 문제 중 하나이다.
저는 height와 width로 나눠서 생각을 해 보았습니다.
height가 1일 때, 2일 때, 3 이상일 때.
이렇게 3가지 경우로 나눠볼 수 있을 것 같습니다.
height가 1일 때 > width가 어떻게 변하더라도 처음 위치에서 움직일 수가 없습니다.
height가 2일 때 > width의 크기에 따라 (+2, +1), (+2, -1)을 번갈아가며 사용할 수 있습니다. 하지만 4번 이동할 경우부터는 모든 방식을 다 이용해야하므로 만족하지 못합니다.
이 경우 나이트가 움직일 수 있었던 width의 index는 1, 3, 5, 7 입니다.
min(4, (width + 1) / 2)
height가 3 이상일 때 > 3 이상일 때부터는 width에 따라 4가지 방법 모두를 이용해 이동할 수 있습니다.
3 이상일 경우에도 width가 7 이상일 때와 7보다 작을 때로 나눌 수 있습니다.
width가 7 이상일 때 > 이 때는 4번 이동하는 동안 4가지 이동 방법을 모두 이용할 수 있습니다.
그 이후로는 (+1, +2), (+1, -2)를 번갈아 사용할 경우에 가장 많은 곳을 방문할 수 있습니다.
width - 2
width가 7보다 작을 때 > 이 때는 4가지 방법을 다 이용할 수는 없습니다.
(+1, +2), (+1, -2)를 번갈아가는 방법으로 계산해야 가장 많은 곳을 방문할 수 있는데, 이렇게 될 경우 도출되는 식은 다음과 같습니다.
min(4, width)
이렇게 경우의 수를 나눠서 계산을 하면 원하는 답을 구할 수 있습니다.
#include <iostream>
#include <algorithm>
using namespace std;
int height, width;
void input() {
cin >> height >> width;
}
int solve() {
if (height == 1) return 1;
else if (height == 2) return min(4, (width + 1) / 2);
else {
if (width >= 7) return width - 2;
else return min(4, width);
}
}
void printAnswer(int ans) {
cout << ans << '\n';
}
int main() {
input();
int ans = solve();
printAnswer(ans);
return 0;
}
'알고리즘' 카테고리의 다른 글
[백준] 10816번: 숫자 카드 2 (0) | 2018.07.30 |
---|---|
[백준] 10815번: 숫자 카드 (0) | 2018.07.29 |
[백준] 10610번: 30 (0) | 2018.06.03 |
[백준] 1744번: 수 묶기 (0) | 2018.06.03 |
[백준] 1541번: 잃어버린 괄호 (0) | 2018.06.02 |