문제 링크
https://www.acmicpc.net/problem/20208
문제
진우는 민트초코우유를 좋아하는 민초단이다. 힘든 일이 있더라도 민트초코우유 하나를 마시면 기운이 펄펄 솟는다고 한다!
민트초코우유를 너무 좋아하는 나머지 진우는 매일 아침 특정 지역들에서 민트초코우유가 배달된다는 N × N 크기의 2차원 민초마을로 이사를 하였다.
진우는 아침에 눈을 뜨면 집에서 민초마을의 지도를 들고 민트초코우유를 찾으러 출발한다. 이때의 초기 체력은 M이다. 여기에서 체력은 진우가 이동할 수 있는 거리를 나타낸다. 진우는 지도상에서 상, 하, 좌, 우로 1칸씩 이동할 수 있으며 이동하면 체력이 1만큼 줄어든다. 진우가 마을을 돌아다니다가 민트초코우유를 마신다면 체력이 H 만큼 증가하며 진우의 체력이 초기체력 이상으로 올라갈 수 있다. 체력이 0이 되는 순간 진우는 이동할 수 없다.
민트초코를 찾으러 돌아다니다가 마을 한복판에서 체력이 0이 되어 집으로 못 돌아가는 상황은 만들어져서는 안된다. 진우가 얼마나 많은 민트초코우유를 마시고 집으로 돌아올 수 있는지 알아보자.
입력
첫번째 줄에 민초마을의 크기인 N과 진우의 초기체력 M, 그리고 민트초코우유를 마실때 마다 증가하는 체력의 양 H가 공백을 두고 주어진다. N, M, H는 모두 10보다 작거나 같은 자연수이다.
두번째 줄부터 N+1번째 줄에 N칸에 걸쳐서 민초마을의 지도가 주어진다. 각 칸은 공백을 두고 주어지며 지도상에서 진우의 집은 1, 민트초코우유는 2로 주어지며 빈 땅은 0으로 주어진다. 진우의 집은 무조건 한 곳이 주어지며 마을에 배달되는 민트초코우유의 총합은 10개를 넘지 않는다.
출력
진우가 집을 나와서 다시 집으로 돌아올 때 까지 마실 수 있는 민트초코우유의 최대 개수를 출력하자.
예제 입력 1
10 2 3
0 0 0 0 0 0 0 0 0 0
0 0 0 2 0 0 0 0 0 0
0 2 0 0 0 0 2 0 0 0
0 0 0 0 0 0 0 0 0 0
0 2 0 0 2 0 0 0 0 0
0 0 0 0 0 0 0 0 2 0
0 0 0 1 0 0 2 0 0 0
0 0 0 0 2 0 0 0 0 0
0 2 0 0 0 0 0 0 0 0
0 0 0 0 0 2 0 0 0 0
예제 출력 1
2
좌측 상단을 (0, 0)이라고 하자. 진우의 집은 (6, 3)에 위치한다. 진우가 이동하는 위치, 체력을 순서대로 표시하면 아래와 같다.
- (6, 3) 2
- (7, 4) 3
- (4, 4) 3
- (6, 3) 0
예제 입력 2
6 8 3
0 0 1 0 0 0
0 2 0 2 0 0
0 0 0 0 0 2
0 0 0 0 0 0
2 0 0 2 2 2
0 0 2 0 0 0
예제 출력 2
8
알고리즘 분류
- 백트래킹
풀이
민트초코우유의 개수는 10개를 넘지 않기 때문에, 민트초코우유의 위치들을 next_permutation()을 활용해 방문 순서들을 바꾸어 가면서 탐색하면 최악의 경우에도 약 360만번 정도의 연산만 하면 되므로 1초 안에 문제를 해결할 수 있게 된다.
처음 우유의 위치와 진우의 집의 위치 간 거리를 구하고 이것이 현재 진우의 체력을 넘지 않는다면 첫 우유까지 도달할 수 있다. 우유를 마신 후 두 번째로 방문할 우유에 도달할 수 있다면 마실 수 있는 우유의 개수는 2개가 되고, 만약에 방문할 수 없다면 마실 수 있는 우유의 개수는 1개가 되는 것이다.
이런 식으로 최대 10!번의 연산을 수행해서 진우가 마실 수 있는 민트초코우유의 최댓값을 구한다.
코드
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#define MAX 11
#define INF 1e9
#define FASTIO cin.tie(0); cout.tie(0);
using namespace std;
int N, M, H;
pair<int, int> Home;
vector<pair<int, int> > Vec;
int Answer = 0;
void input() {
cin >> N >> M >> H;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
int C;
cin >> C;
if (C == 1) {
Home = make_pair(i, j);
}
else if (C == 2) {
Vec.push_back(make_pair(i, j));
}
}
}
}
void settings() {
do {
int Health = M;
int Count = 0;
pair<int, int> Now = Home;
for (int i = 0; i < Vec.size(); i++) {
int Len = abs(Now.first - Vec[i].first) + abs(Now.second - Vec[i].second);
if (Health >= Len) {
Health -= Len;
Health += H;
Now = Vec[i];
int Back = abs(Now.first - Home.first) + abs(Now.second - Home.second);
if (Health >= Back) {
Count = i + 1;
}
}
else {
break;
}
}
Answer = max(Answer, Count);
} while (next_permutation(Vec.begin(), Vec.end()));
}
void find_Answer() {
cout << Answer << "\n";
}
int main() {
FASTIO
input();
settings();
find_Answer();
return 0;
}
'BOJ > Gold' 카테고리의 다른 글
[BOJ/Gold 5] 백준 12908 텔레포트 3(C++) (0) | 2022.12.25 |
---|---|
[BOJ/Gold 5] 백준 18428 감시 피하기(C++) (0) | 2022.12.25 |
[BOJ/Gold 5] 백준 19942 다이어트(C++) (0) | 2022.12.12 |
[BOJ/Gold 4] 백준 6135 Cow Hurdles(C++) (0) | 2022.12.07 |
[BOJ/Gold 4] 백준 9870 Vacation Planning(C++) (1) | 2022.12.07 |