danbibibi
article thumbnail

문제

문제 바로가기> BOJ 2842번 : 집배원 한상덕

 

2842번: 집배원 한상덕

상덕이는 언덕 위에 있는 마을의 우체국에 직업을 얻었다. 마을은 N×N 행렬로 나타낼 수 있다. 행렬로 나뉘어진 각 지역은 우체국은 'P', 집은 'K', 목초지는 '.' 중 하나로 나타낼 수 있다. 또, 각

www.acmicpc.net

 

풀이

고도를 ±1 씩 모든 경우의 수를 구할 경우 시간 초과가 발생한다. 50*50*1,000,000 = 2,500,000,000 (25억,,)

하지만 실제 고도의 개수는 50*50 = 2500을 초과할 수 없고, 이를 반영해서 "투 포인터 + 그래프 탐색"으로 풀었다.

 

1. 투포인터를 이용하기 위해 고도를 정렬해야 한다.

   이때, 중복되는 값은 필요 없으므로!! set을 이용해서 중복되는 값을 제거해주었다.

 

2. 투포인터를 이용해서 (low ~ high) 고도 내에서 모든 집에배달이 가능한지 확인한다.

    배달이 불가한 경우, high를 올려준다! (엇? 넘을 수없는 문턱이 있어,,! 배달 불가야!)

    배달이 가능한 경우, low를 올려준다! (어라? 피로도 더 줄일 수 있을 거 같은데? 라는 마인드로!)

 

    ++ 우체국에서 출발하므로, 우체국의 고도는 반드시 포함되어야 한다!

    

 

#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<set>
#define MAX 51
#define INF 1000001
using namespace std;

int N;
int py, px;
int home_cnt=0;
set<int> setAltitude;
vector<int> vecAltitude;

char town[MAX][MAX];
bool visited[MAX][MAX];
int altitude[MAX][MAX];
int dy[] = {0, -1, -1, -1, 0, 1, 1, 1};
int dx[] = {-1, -1, 0, 1, 1, 1, 0, -1};

void input(){
	cin >> N;

	string line;
	for(int i=0; i<N; i++){
		cin >> line;
		for(int j=0; j<N; j++) {
			town[i][j] = line[j];
			if(town[i][j] == 'P') {py=i; px=j;}
			else if(town[i][j] == 'K') home_cnt++;
		}
	}
	for(int i=0; i<N; i++){
		for(int j=0; j<N; j++){
			cin >> altitude[i][j];
			setAltitude.insert(altitude[i][j]);
		}
	}

	for(auto iter : setAltitude) vecAltitude.push_back(iter);
	sort(vecAltitude.begin(), vecAltitude.end());
}

int dfs(int y, int x, int low, int high){
	visited[y][x] = true;
	int cnt = 0;
	for(int d=0; d<8; d++){
		int ny = y+dy[d];
		int nx = x+dx[d];
		if(ny<0 || ny>=N || nx<0 || nx>=N || visited[ny][nx]) continue; // 범위를 벗어난 경우, 이미 방문한 경우
		if(altitude[ny][nx]<low || altitude[ny][nx]>high) continue; // 범위 내 고도에서 방문 불가한 경우
		if(town[ny][nx] == 'K') cnt++;
		cnt+=dfs(ny, nx, low, high);
	}
	return cnt;
}

void solution(){ // 가장 작은 피로도
	int l=0, r=0, ans=INF;
	while (r < vecAltitude.size()) {
		int low = vecAltitude[l], high=vecAltitude[r];
		if(altitude[py][px]<low || altitude[py][px]>high) { r++; continue;} // 우체국 고도를 포함하지 않는 경우 (우체국에서 출발)
		memset(visited, false, sizeof(visited));
		if(dfs(py, px, low, high)==home_cnt){
			ans = min(ans, high-low);
			l++;
		}
		else r++;
	}
	cout << ans;
}

int main(){
	ios_base::sync_with_stdio(0); cin.tie(0);
	input();
	solution();
}

'문제 풀이 > 백준' 카테고리의 다른 글

BOJ 1584번: 게임  (0) 2023.03.18
BOJ 2636번: 치즈  (0) 2023.03.18
BOJ 1918번: 후위 표기식  (0) 2023.03.07
BOJ 21758번: 꿀 따기  (0) 2023.02.25
BOJ16946번: 벽 부수고 이동하기 4  (0) 2023.02.25
profile

danbibibi

@danbibibi

꿈을 꾸는 시간은 멈춰 있는 것이 아냐 두려워하지 마 멈추지 마 푸른 꿈속으로