https://www.acmicpc.net/problem/26076
26076번: 곰곰이의 식단 관리 2
$N$행 $M$열 크기의 격자판이 있고, 이 격자판의 $(N,M)$ 위치에는 맛있는 치킨이 놓여 있다. 곰곰이는 $(1,1)$ 에서 출발하여 치킨을 향해 이동하려 한다. 곰곰이는 상하좌우 방향으로 자유롭게 이동
www.acmicpc.net
풀이
0. 문제를풀기 앞서서 풀어야되는 문제
https://www.acmicpc.net/problem/2667
2667번: 단지번호붙이기
<그림 1>과 같이 정사각형 모양의 지도가 있다. 1은 집이 있는 곳을, 0은 집이 없는 곳을 나타낸다. 철수는 이 지도를 가지고 연결된 집의 모임인 단지를 정의하고, 단지에 번호를 붙이려 한다. 여
www.acmicpc.net
BFS를 사용해서 풀겁니다. BFS의 그룹마다 번호도 붙여야되므로 해당 문제가 필수입니다.
1. 핵심 아이디어
모서리에 있는 곰곰이나 치킨만 가두면되므로 장애물은 많아야 2개만 깔면된다.
즉 답으로 나올 수 있는 경우의 최대 갯수는 2개라는 뜻이다.

그렇다면 장애물을 0개 or 1개 세우는 경우는 어떠한 경우가 있을까?
0개 세우는 경우를 파악하는 방법은 간단하다.
곰곰이와 치킨의 공간이 두 공간으로 나뉘었는지 파악하면된다.
BFS를 통해서 곰곰이에서 치킨까지 도달 할 수 있는지 확인해본다.

1개를 세우는 방법은 다음과 같다.

격자판의 밖에 다음과 같은 빨강색과 파란색으로 장애물이 더 있다고 생각하고
빨강장애물과 연결된 장애물과 파란장애물과 연결된 장애물을 표시해보면 다음과 같이 나온다.

장애물을 배치할 공간중에서 ←→↑↓↖↗↙↘의 칸을 확인해서 파랑장애물과 빨간장애물을 모두 포함하고 있다면
해당 공간에 장애물을 배치하면 치킨과 곰곰이를 분리할 수 있다는 것을 알 수 있다.

조금 조심해야되는 부분을 찝어준다면

외각부분은 다음과 같이 되므로 예외처리해야한다.
필자는 이 부분때문에 틀렸습니다 를 받았다. ㅠㅠ
코드
#include <bits/stdc++.h>
#pragma warning(disable:4996)
using namespace std;
#define endl "\n"
#define int long long
#define float long double
const float INF = 1e10;
const int Dic[8][2] = { {0,1},{0,-1},{1,0},{-1,0} ,{1,1},{-1,-1},{1,-1},{-1,1} };
////////////////////////////////////////////////////////////////////////
int N, M;
int MAP[2005][2005];
bool ZeroCheck()
{
vector<vector<bool>> Visit(N, vector<bool>(M, false));
queue<pair<int, int>> Q;
Q.push({ 0,0 });
Visit[0][0] = true;
while (Q.empty() == false)
{
pair<int, int> now = Q.front();
Q.pop();
for (int i = 0; i < 4; i++)
{
int ar = now.first + Dic[i][0];
int ac = now.second + Dic[i][1];
if (ar < 0 || ac < 0 || ar >= N || ac >= M)
continue;
if (MAP[ar][ac] == 1)
continue;
if (Visit[ar][ac])
continue;
Q.push({ ar, ac });
Visit[ar][ac] = true;
}
}
return (Visit[N - 1][M - 1] == false);
}
bool OneCheck()
{
vector<vector<int>> Visit(N, vector<int>(M, 0));
{
queue<pair<int, int>> Q1;
for (int i = 0; i < N; i++)
if (MAP[i][0] == 1)
{
Q1.push({ i,0 });
Visit[i][0] = 1;
}
for (int i = 0; i < M; i++)
if (MAP[N - 1][i] == 1)
{
Q1.push({ N - 1,i });
Visit[N - 1][i] = 1;
}
while (Q1.empty() == false)
{
pair<int, int> now = Q1.front();
Q1.pop();
for (int i = 0; i < 8; i++)
{
int ar = now.first + Dic[i][0];
int ac = now.second + Dic[i][1];
if (ar < 0 || ac < 0 || ar >= N || ac >= M)
continue;
if (MAP[ar][ac] == 0)
continue;
if (Visit[ar][ac] > 0)
continue;
Q1.push({ ar, ac });
Visit[ar][ac] = 1;
}
}
}
{
queue<pair<int, int>> Q2;
for (int i = 0; i < M; i++)
if (MAP[0][i] == 1)
{
Q2.push({ 0,i });
Visit[0][i] = 2;
}
for (int i = 0; i < N; i++)
if (MAP[i][M - 1] == 1)
{
Q2.push({ i,M - 1 });
Visit[i][M - 1] = 2;
}
while (Q2.empty() == false)
{
pair<int, int> now = Q2.front();
Q2.pop();
for (int i = 0; i < 8; i++)
{
int ar = now.first + Dic[i][0];
int ac = now.second + Dic[i][1];
if (ar < 0 || ac < 0 || ar >= N || ac >= M)
continue;
if (MAP[ar][ac] == 0)
continue;
if (Visit[ar][ac] > 0)
continue;
Q2.push({ ar, ac });
Visit[ar][ac] = 2;
}
}
}
for (int i = 0; i < N; i++)
for (int j = 0; j < M; j++)
{
if (i == 0 && j == 0)
continue;
if (i == N - 1 && j == M - 1)
continue;
if (MAP[i][j] != 0)
continue;
bool one = false;
bool two = false;
for (int k = 0; k < 8; k++)
{
int ai = i + Dic[k][0];
int aj = j + Dic[k][1];
if (ai < 0 || aj < 0 || ai >= N || aj >= M)
{
if (ai < 0)
two = true;
if (ai >= N)
one = true;
if (aj < 0)
one = true;
if (aj >= M)
two = true;
continue;
}
if (Visit[ai][aj] == 1)
one = true;
if (Visit[ai][aj] == 2)
two = true;
}
if (one && two)
return true;
}
return false;
}
int32_t main()
{
ios_base::sync_with_stdio(false);
std::cin.tie(NULL);
std::cout.tie(NULL);
std::cin >> N >> M;
for (int i = 0; i < N; i++)
for (int j = 0; j < M; j++)
std::cin >> MAP[i][j];
if (ZeroCheck())
{
std::cout << "0" << endl;
return 0;
}
if (OneCheck())
{
std::cout << "1" << endl;
return 0;
}
std::cout << "2" << endl;
return 0;
}
'알고리즘 > 문제풀이' 카테고리의 다른 글
백준 24425 タクシー 2 (Taxis 2) (0) | 2022.12.28 |
---|---|
백준 26073 외로운 곰곰이는 친구가 있어요 (0) | 2022.12.04 |
백준 15997 승부 예측 (0) | 2022.11.27 |
백준 26009 험난한 등굣길 (0) | 2022.11.26 |
백준 25945 컨테이너 재배치 (1) | 2022.11.25 |