백준 17822 원판돌리기
본문 바로가기
알고리즘 모음집/알고리즘 (Algorithm)

백준 17822 원판돌리기

by KyeongMin 2019. 11. 12.
728x90
반응형

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

 

17822번: 원판 돌리기

반지름이 1, 2, ..., N인 원판이 크기가 작아지는 순으로 바닥에 놓여있고, 원판의 중심은 모두 같다. 각각의 원판에는 M개의 정수가 적혀있고, i번째 원판에 적힌 j번째 수의 위치는 (i, j)로 표현한다. 수의 위치는 다음을 만족한다. (i, 1)은 (i, 2), (i, M)과 인접하다. (i, M)은 (i, M-1), (i, 1)과 인접하다. (i, j)는 (i, j-1), (i, j+1)과 인접하다. (2 ≤ j ≤ M-1) (1, j)는 (

www.acmicpc.net

#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;
#define NS 52
#define MS 52
int N, M, T;
int num[NS][MS];
int xi, di, ki;
int chk[NS][MS];
int dy[] = { 0,1,0,-1 };
int dx[] = { 1,0,-1,0 };
int flag;// 나중에 지워진적 없는지 있는지 파악하기위해
int flag1;
int ret;
void sumNum() {
	for (int i = 1; i <= N; i++) {
		for (int j = 1; j <= M; j++) {
			ret += num[i][j];
		}
	}
}
void dfs(int y, int x, int sameNum) {
	for (int dir = 0; dir < 4; dir++) {
		int ny = y + dy[dir]; int nx = x + dx[dir];
		if (ny <= 0||ny>N)continue;
		if (nx <= 0)nx = M;
		if (nx > M)nx = 1;
		if (chk[ny][nx] == 0 && num[ny][nx] == sameNum && num[ny][nx] != 0) {
			chk[ny][nx] = 1;
			num[ny][nx] = 0;
			flag = 1;
			dfs(ny, nx, sameNum);
		}

	}
}
void searchNum() {
	flag1 = 0;
	memset(chk, 0, sizeof(chk));
	for (int i = 1; i <= N; i++) {
		for (int j = 1; j <= M; j++) {
			if (chk[i][j] == 0 && num[i][j] != 0) {
				flag = 0;
				chk[i][j] = 1;
				dfs(i, j, num[i][j]);
				if (flag == 1) {//한개라도 중복되서 지웠으면
					num[i][j] = 0;
					flag1 = 1;
				}
			}
		}
	}
}
void rightClock(int y) {//0 시계방향
	int snum = num[y][M];
	for (int x = M - 1; x >= 1; x--) {
		num[y][x + 1] = num[y][x];
	}
	num[y][1] = snum;//끝값 저장
}
void leftClock(int y) {//1 반시게 방향
	int sum = num[y][1];
	for (int x = 2; x <= M; x++) {
		num[y][x - 1] = num[y][x];
	}
	num[y][M] = sum;
}
void calNum(int sum, int cnt) {
	float a = (float)sum / cnt;
	for (int i = 1; i <= N; i++) {
		for (int j = 1; j <= M; j++) {
			if (num[i][j] != 0 && num[i][j] < a) {
				num[i][j]++;
			}
			else if (num[i][j] != 0 && num[i][j] > a) {
				num[i][j]--;
			}
		}
	}
}
void rotCir() {//원판 돌리기 시뮬
	for (int t = 0; t < T; t++) {
		scanf("%d %d %d", &xi, &di, &ki);
		for (int i = 1; i <= N; i++) {// 너무 너무한 치명적 실수M으로 해서 틀렸었음
			if (i % xi == 0) {//xi의 배수이면
				if (di == 0) {
					for (int k = 0; k < ki; k++) {
						rightClock(i);
					}
				}
				else if (di == 1) {
					for (int k = 0; k < ki; k++) {
						leftClock(i);
					}
				}
			}
		}
		searchNum();
		if (flag1 == 0) {
			int sum = 0;
			int cnt = 0;
			for (int i = 1; i <= N; i++) {
				for (int j = 1; j <= M; j++) {
					sum += num[i][j];
					if (num[i][j] != 0) {
						cnt++;
					}
				}
			}
			//sum = sum / cnt;//평균값
			if (cnt != 0)
				calNum(sum, cnt);
		}
	}
}
void init() {
	scanf("%d %d %d", &N, &M, &T);
	for (int i = 1; i <= N; i++) {
		for (int j = 1; j <= M; j++) {
			scanf("%d", &num[i][j]);
		}
	}
	rotCir();
	sumNum();
}
int main(void) {
	init();
	cout << ret << endl;
	return 0;
}

흠 이문제는 진짜 쉬운데 포인트를 하나 말하자면 배열은 직선이고 여기서 원하는 것은 원이기때문에 

직선인 배열을 원같이쓰기만 한다면 쉽게 풀리는 문제입니다. 물론 실수를 좀 범해서 좀 걸렸지만 초보자들도 쉽게 

풀만한 문제 같습니다. 그럼 오늘은 너무 피곤해서 여기까지..

728x90
반응형

댓글