1일1알

백준 17822번 원판 돌리기 C++ 본문

알고리즘

백준 17822번 원판 돌리기 C++

영춘권의달인 2022. 10. 4. 20:55

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

 

17822번: 원판 돌리기

반지름이 1, 2, ..., N인 원판이 크기가 작아지는 순으로 바닥에 놓여있고, 원판의 중심은 모두 같다. 원판의 반지름이 i이면, 그 원판을 i번째 원판이라고 한다. 각각의 원판에는 M개의 정수가 적혀

www.acmicpc.net

 

직접 돌리지는 않고 offset을 이용해서 현재 원판의 위치를 찾는식으로 문제를 해결하였다.

변수 하나를 실수로 잘못써서 시간을 좀 많이 썼다..

 

#include <iostream>
#include <string>
#include <vector>
#include <math.h>
#include <algorithm>
#include <utility>
#include <stack>
#include <queue>
#include <math.h>
#include <set>
#include <map>
#include <list>
#include <unordered_map>
#include <unordered_set>
#include <iomanip>
#include <limits.h>

using namespace std;
using int64 = long long;

int n, m, t;

int dN[4] = { -1,1,0,0 };
int dM[4] = { 0,0,1,-1 };

vector<int> offsets;
vector<vector<float>> board;
vector<vector<bool>> erased;

bool isErase = false;

void Bfs(int _n, int _m) {

	float val = board[_n][_m];
	int sameCnt = 0;
	for (int i = 0; i < 4; i++) {
		int nextN = _n + dN[i];
		int nextM = _m + dM[i];
		if (nextN <= 0 || nextN > n) continue;
		if (nextN != _n) {
			nextM = nextM - offsets[_n] + offsets[nextN];
		}
		nextM = (nextM + m) % m;
		if (erased[nextN][nextM]) continue;
		if (val != board[nextN][nextM]) continue;
		sameCnt++;
	}
	if (sameCnt == 0) return;
	isErase = true;
	queue<pair<int, int>> q;
	q.push({ _n,_m });
	erased[_n][_m] = true;
	while (!q.empty()) {
		auto curr = q.front();
		q.pop();

		for (int i = 0; i < 4; i++) {
			int nextN = curr.first + dN[i];
			int nextM = curr.second + dM[i];
			if (nextN <= 0 || nextN > n) continue;
			if (nextN != curr.first) nextM = nextM - offsets[curr.first] + offsets[nextN];
			nextM = (nextM + m) % m;
			if (erased[nextN][nextM]) continue;
			if (val != board[nextN][nextM]) continue;
			erased[nextN][nextM] = true;
			q.push({ nextN,nextM });
		}
	}
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
	cout.tie(NULL);

	cin >> n >> m >> t;
	offsets = vector<int>(n + 1, 0);
	board = vector<vector<float>>(n + 1, vector<float>(m));
	erased = vector<vector<bool>>(n + 1, vector<bool>(m, false));
	for (int i = 1; i <= n; i++) {
		for (int j = 0; j < m; j++) {
			cin >> board[i][j];
		}
	}
	for (int i = 0; i < t; i++) {
		int x, d, k;
		cin >> x >> d >> k;
		int offset;
		if (d == 0) offset = -k;
		else offset = k;
		for (int j = x; j <= n; j += x) {
			offsets[j] += offset;
			offsets[j] = (offsets[j] + m) % m;
		}
		for (int j = 1; j <= n; j++) {
			for (int k = 0; k < m; k++) {
				int currIdx = (k + offsets[j]) % m;
				if (erased[j][currIdx]) continue;
				Bfs(j, currIdx);
			}
		}

		if (isErase == false) {
			float sum = 0;
			float avr;
			int cnt = 0;
			for (int j = 1; j <= n; j++) {
				for (int k = 0; k < m; k++) {
					if (erased[j][k]) continue;
					cnt++;
					sum += board[j][k];
				}
			}
			if (cnt != 0) {
				avr = sum / cnt;
				for (int j = 1; j <= n; j++) {
					for (int k = 0; k < m; k++) {
						if (erased[j][k]) continue;
						if (board[j][k] > avr) board[j][k] -= 1.f;
						else if (board[j][k] < avr) board[j][k] += 1.f;
					}
				}
			}
		}

		isErase = false;
	}
	double ans = 0;
	for (int i = 1; i <= n; i++) {
		for (int j = 0; j < m; j++) {
			if (erased[i][j]) continue;
			ans += board[i][j];
		}
	}
	cout << int(ans);
}

'알고리즘' 카테고리의 다른 글

백준 5397번 키로거 C++  (0) 2022.10.09
백준 1699번 제곱수의 합 C++  (0) 2022.10.08
백준 2212번 센서 C++  (1) 2022.10.03
백준 2473번 세 용액 C++  (0) 2022.10.02
백준 17404번 RGB거리 2 C++  (1) 2022.09.30