PS

백준 16957번 체스판 위의 공

남마허 2020. 3. 24. 12:55

https://www.acmicpc.net/problem/16957

 

16957번: 체스판 위의 공

크기가 R×C인 체스판이 있고, 체스판의 각 칸에는 정수가 하나씩 적혀있다. 체스판에 적혀있는 정수는 모두 서로 다르다. 체스판의 각 칸 위에 공을 하나씩 놓는다. 이제 공은 다음과 같은 규칙에 의해서 자동으로 움직인다. 인접한 8방향 (가로, 세로, 대각선)에 적힌 모든 정수가 현재 칸에 적힌 수보다 크면 이동을 멈춘다. 그 외의 경우에는 가장 작은 정수가 있는 칸으로 공이 이동한다. 공의 크기는 매우 작아서, 체스판의 한 칸 위에 여러 개의 공이 있을

www.acmicpc.net

 

 

 

 

 

<접근방법>

접근 방법이 다양한 문제입니다.

저는 그냥 bfs, 우선순위 큐를 활용한 bfs, dp로 풀었습니다.

 

공은 큰 곳에서 작은 곳으로 흐르기 때문에 우선순위 큐를 활용해 풀 수 있습니다.

 

 

 

1 - 2 - 3 - 4

2 - 3 - 4

 

1 -> 4인 공괴 2 -> 4 인 공은 경로가 겹칩니다.

이 경로를 저장해놓고 중복 탐색을 방지하는 dp로 문제를 풀 수 있습니다.

 

<느낀 점>

중복탐색 - dp

 

 


 

 

 

<코드>

#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;

struct point {
	int val, y, x;
};

int n, m;
int map[500][500], visit[500][500];
int dy[8] = { 1, -1, 0, 0, 1, 1, -1, -1 };
int dx[8] = { 0, 0, 1, -1, 1, -1, 1, -1 };

struct cmp {
	bool operator()(point a, point b) {
		return a.val < b.val;
	}
};

priority_queue<point, vector<point>, cmp> q;

void bfs() {
	while (!q.empty()) {
		point t = q.top();
		q.pop();

		if (visit[t.y][t.x] == 0) continue;

		int tmp = 987654321;
		int my, mx;
		for (int i = 0; i < 8; i++) {
			int ny = t.y + dy[i];
			int nx = t.x + dx[i];

			if (ny < 0 || ny >= n || nx < 0 || nx >= m) continue;

			if (tmp > map[ny][nx]) {
				tmp = map[ny][nx];
				my = ny;
				mx = nx;
			}
		}
		if (tmp <= map[t.y][t.x]) {
			visit[my][mx] += visit[t.y][t.x];
			visit[t.y][t.x] = 0;
			q.push({map[my][mx], my, mx });
		}
	}
}

int main() {
	cin >> n >> m;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			cin >> map[i][j];

			q.push({map[i][j], i, j });
			visit[i][j]++;
		}
	}

	bfs();

	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			cout << visit[i][j] << ' ';
		}
		puts("");
	}

	return 0;
}
#include <iostream>
#include <algorithm>
#include <memory.h>
using namespace std;

struct point {
	int y, x;
};

int n, m;
int map[501][501], ans[501][501];
bool visit[501][501];
point cache[501][501];
int dy[8] = { 1, -1, 0, 0, 1, 1, -1, -1 };
int dx[8] = { 0, 0, 1, -1, 1, -1, 1, -1 };

point dfs(int y, int x) {
	point &res = cache[y][x];
	bool &visited = visit[y][x];
	if (visited) return res;
	visited = true;

	//res.y = y; res.x = x;
	res = {y, x};
	int now_val = map[y][x];
	int ty, tx;
	for (int i = 0; i < 8; i++) {
		int ny = y + dy[i];
		int nx = x + dx[i];

		if (ny < 0 || ny >= n || nx < 0 || nx >= m) continue;

		if (now_val > map[ny][nx]) {
			now_val = map[ny][nx];
			ty = ny;
			tx = nx;
		}
	}
	if (now_val != map[y][x]) return res = dfs(ty, tx);
	return res;
}

int main() {
	cin >> n >> m;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			cin >> map[i][j];
		}
	}

	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			point t = dfs(i, j);

			ans[t.y][t.x]++;
		}
	}

	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			cout << ans[i][j] << ' ';
		}
		puts("");
	}


	return 0;
}

 

 

 

 

 

반응형