[BOJ][실5][1783] 병든 나이트
문제 링크
첫 번째 풀이 : 그리디
알고리즘
- 4번 이상 움직이기 위해서는 이동방법 1,2,3,4를 모두 사용해야 합니다.
- 4번 미만 움직일 때는 이동방법이 상관 없습니다.
문제에서 구해야하는 것은 한 번의
여행에서 방문할 수 있는 칸의 최대 갯수입니다.
이동 방식에 대해서는 아래와 같이 나타낼 수 있습니다.
1
2
int dx[4] = { -2,-1,1,2 };
int dy[4] = { 1,2,2,1 };
생각을 해보면, 시작 위치에서 가로는 1칸 또는 2칸이 움직입니다. 세로는 -2칸 ~ +2칸이 움직입니다. 그래서 세로를 기준으로 케이스는 나누어서 생각하는 것이 좋습니다. 가로는 최대 2칸, 세로는 최대 4칸 차이나는데, 입력받은 가로가 세로보다 두 배가 크더라도 가능하도록 case를 나누어야 합니다.
Case work
라고 하여 Case를 나누어서 생각해보아야하는 문제 중에서, 가장 가장 많이 푼 문제가 이 문제입니다.
- 높이 = 1 : 시작점에서 움직일 수 없으므로 정답은 1개
- 높이 = 2 : 이동방식 2번과 3번을 번갈아서 사용하면 이동할 수 있습니다. 대신 4번 이상 움직이기 위해서는 이동방식을 모두 사용해야하기 때문에 최대 3번까지만 움직일 수 있습니다. 2번,3번만을 사용하면 홀수에만 도달할 수 있고, 최대 3번까지의 여행만 할 수 있으므로 정답은 min(4, (m+1)/2)
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
---|---|---|---|---|---|---|---|---|
x | x | |||||||
x | x | x(불가능) |
- 높이 >= 3 : 높이를 최대한 덜 변화시키면서 이동방식을 모두 사용하는 방법은 아래와 같습니다. 즉, 높이가 3이상이라면 가로의 길이를 모두 활용할 수 있는 최소 조건이 만족된 것입니다. 아래의 표를 보면 n은 변하지 않고 m만 6칸 움직이고 모든 이동방식을 사용했습니다. 이제부터는 유리한 이동방법을 고르고 계속 사용해도 됩니다. 1번+4번을 반복하면 7이상의 모든 m번째 행을 방문할 수 있습니다. 따라서 정답은 아래와 같습니다.
1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|
x | ||||||
x | ||||||
x | x | x |
1
2
3
4
5
if(n>=3){
if(m <=3) ans = m;
else if(m <=6) ans = 4;
else ans = m - 2;
}
또는
1
2
3
4
if(n>=3){
if(m <=6) ans = min(4,m);
else ans = m - 2;
}
정답코드
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
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<int, int>;
const int MAX = 2'000'000'000;
int n, m, k;
int main()
{
//freopen("input.txt", "r", stdin);
ios_base::sync_with_stdio(0); cin.tie(0);
cin >> n >> m;
int ans = 0;
if (n == 1) ans = 1;
else if (n == 2) ans = min(4, (m + 1) / 2);
else {
if (m <= 6) ans = min(4, m);
else ans = m - 2;
}
cout << ans;
return 0;
}
Success Notice: 수고하셨습니다.
Leave a comment