본문 바로가기
백준 알고리즘/DFS

원판 돌리기 C++

by paysmile 2021. 10. 16.

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

 

17822번: 원판 돌리기

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

www.acmicpc.net

#include <iostream>
#include <vector>

using namespace std;
int n, m, t;
vector<vector<int>> v;
int x, d, k;
int answer = 0;
struct MOVE { int x, y; };
MOVE mv[4] = { {1,0}, {-1,0}, {0,1}, {0,-1} };
vector<vector<int>> visited(n + 1);
bool del = false;

void MoveCircle1(int num, int k) { //시계방향
	vector<int> tmp = v[num];
	int index = m - k;

	for (int i = 0; i < m; i++) {
		if (index == m) {
			index = 0;
		}
		v[num][i] = tmp[index];
		index++;
	}
}

void MoveCircle2(int num, int k) { //반시계방향
	vector<int> tmp = v[num];
	int index = k;

	for (int i = 0; i < m; i++) {
		if (index == m) {
			index = 0;
		}
		v[num][i] = tmp[index];
		index++;
	}
}

void dfs(int mi, int mj,int value) {

	if (mj == 0) {
		int movei = mi;
		int movej = m - 1;

		if (movei > 0 && movei <= n && movej >= 0 && movej < m) {
			if (visited[movei][movej] == -1 && v[movei][movej] == value) {
				visited[movei][movej] = 1;
				del = true;
				v[mi][mj] = 0;
				v[movei][movej] = 0;
				dfs(movei, movej, value);
			}
		}
	}

	if (mj == m - 1) {
		int movei = mi;
		int movej = 0;

		if (movei > 0 && movei <= n && movej >= 0 && movej < m) {
			if (visited[movei][movej] == -1 && v[movei][movej] == value) {
				visited[movei][movej] = 1;
				del = true;
				v[mi][mj] = 0;
				v[movei][movej] = 0;
				dfs(movei, movej, value);
			}
		}
	}

	for (int k = 0; k < 4; k++) {
		int movei = mi + mv[k].x;
		int movej = mj + mv[k].y;

		if (movei > 0 && movei <= n && movej >= 0 && movej < m) {
			if (visited[movei][movej] == -1 && v[movei][movej] == value) {
				visited[movei][movej] = 1;
				del = true;
				v[mi][mj] = 0;
				v[movei][movej] = 0;
				dfs(movei, movej,value);
			}
		}
	}
}

bool Samenum() {
	visited.clear();
	visited.resize(n + 1);
	del = false;

	for (int i = 1; i <= n; i++) {
		for (int j = 0; j < m; j++) {
			visited[i].push_back(-1);
		}
	}

	for (int i = 1; i <= n; i++) {
		for (int j = 0; j < m; j++) {
			if (visited[i][j] == -1 && v[i][j] != 0) {
				dfs(i, j,v[i][j]);
			}
		}
	}

	return del;
}

void CalEvg() {
	double sum = 0;
	int count = 0;

	for (int i = 1; i <= n; i++) {
		for (int j = 0; j < m; j++) {
			sum += v[i][j];
			if (v[i][j] != 0)	count++;
		}
	}

	double avg = sum / count;

	for (int i = 1; i <= n; i++) {
		for (int j = 0; j < m; j++) {
			if (v[i][j] == 0)	continue;
			if (v[i][j] > avg)	v[i][j] -= 1;
			else if (v[i][j] < avg)	v[i][j] += 1;
		}
	}
}

int main(void) {
	cin >> n >> m >> t;

	v.resize(n+1);
	for (int i = 1; i <= n; i++) {
		for (int j = 0; j < m; j++) {
			int t;
			cin >> t;
			v[i].push_back(t);
		}
	}

	for (int testcase = 0; testcase < t; testcase++) {
		cin >> x >> d >> k;
		for (int i = 1; x*i <= n; i++) {
			int num = i*x;
			if (d == 0)	MoveCircle1(num, k); //시계방향
			else if (d == 1)	MoveCircle2(num, k); //반시계방향
		}
		if (Samenum() == false) {
			CalEvg();
		}
	}

	for (int i = 1; i <= n; i++) {
		for (int j = 0; j < m; j++) {
			answer += v[i][j];
		}
	}
	cout << answer << endl;
}

'백준 알고리즘 > DFS' 카테고리의 다른 글

주사위 굴리기 2  (0) 2021.12.04
마법사 상어와 파이어스톰 C++  (0) 2021.09.22
상어 중학교 C++  (0) 2021.09.18
원판 돌리기  (0) 2021.04.20
마법사 상어와 파이어스톰  (0) 2021.04.01