코딩

[BOJ] 23291 어항정리

코재1 2022. 1. 5. 17:17

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

 

23291번: 어항 정리

마법사 상어는 그동안 배운 마법을 이용해 어항을 정리하려고 한다. 어항은 정육면체 모양이고, 한 변의 길이는 모두 1이다. 상어가 가지고 있는 어항은 N개이고, 가장 처음에 어항은 일렬로 바

www.acmicpc.net

A. 아이디어 및 사용한 자료구조와 알고리즘

특별히 사용한 자료구조나 알고리즘은 없다. 이 문제의 경우 특별한 것이 아닌 말 그대로의 구현을 원하는 것 같았다. 얼마나 효율적으로, compact하게 구현을 하느냐에 달려있는 듯 했다. 첫번째 정리를 하는 함수 setup(), 두번째 정리를 하는 함수 half_setup() 그리고 마지막으로 setup작업이 끝날 때마다 물고기를 나누고 1자로 다시 재배치하는 divide()함수를 만들어 주었다.

 

B. 코드

#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
#include <cmath>
#include <memory.h>
using namespace std;

int tower[100][100] = { 0, };
int n, k;
int dy[4] = { 0,-1,0,1 };
int dx[4] = { -1,0,1,0 };
void setup()
{
	int lx=1, ly=1;
	int  sx=0;
	int min = tower[0][0];
	
	for (int i = 1; i < n; i++)
		if (min >tower[0][i])
			min = tower[0][i];
	for (int i = 0; i < n; i++)
		if (min == tower[0][i])
			tower[0][i]++;
	
	while (ly <= n - sx - lx)
	{
		for (int y = 0; y < ly; y++)
		{
			for (int x = 0; x < lx; x++)
			{
				tower[lx - x][sx+lx+y] = tower[y][x + sx];
				tower[y][x + sx] = 0;
			}
		}
		
		sx += lx;
		if (lx == ly)
			ly++;
		else
			lx++;
	}
}
void divide()
{
	int t_scan[100][100];
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++)
			t_scan[i][j] = tower[i][j];

	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n; j++)
		{
			if (!t_scan[i][j])
				continue;
			for (int x = 0; x < 4; x++)
			{
				int nx = i + dx[x];
				int ny = j + dy[x];

				if (!t_scan[i][j])
					continue;
				int give = t_scan[nx][ny] - t_scan[i][j];
				if (give >= 5)
				{
					give /= 5;
					tower[nx][ny] -= give;
					tower[i][j] += give;
				}
			}
		}
	}

	int arrange = 0;
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n; j++)
		{
			if (!tower[j][i])
				continue;
			if (0 == j && arrange == i)
			{
				arrange++;
				continue;
			}
			tower[0][arrange++] = tower[j][i];
			tower[j][i] = 0;
		}
	}
}

void half_setup()
{
	for (int x = 0; x < n / 2; x++)
	{
		tower[1][n - x - 1] = tower[0][x];
		tower[0][x] = 0;
	}

	for (int y = 0; y < 2; y++)
	{
		for (int x = n / 2; x < n * 3 / 4; x++)
		{
			tower[3 - y][n - 1 + n / 2 - x] = tower[y][x];
			tower[y][x] = 0;
		}
	}
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);

	
	int count = 0, diff=9999;
	cin >> n >> k;
	for (int i = 0; i < n; i++)
		cin >> tower[0][i];
	

	while (1)
	{
		setup();
		divide();


		half_setup();
		divide();

		int max = tower[0][0];
		int min = tower[0][n - 1];
		for (int i = 0; i < n; i++)
		{
			if (max < tower[0][i])
				max = tower[0][i];
			if (min > tower[0][i])
				min = tower[0][i];
		}
		diff = max - min;

		count++;

		if (diff <= k)
			break;
	}

	cout << count;

}

 

C. 후기

구현은 그렇게까지 어렵지 않아서 왜 골드 1문제인지 의아했다. 예제를 다 통과한 반면 마지막 제출에서 계속 실패로 뜬다. 아직까지도 왜그런지 잘 모르겠다. 질문도 없고 혹시나 조건도 확인해봤는데 문제가 없는 것 같은데 계속 실패라고 뜬다. 혹시라도 이상한 점이 발견되면 알려주면 감사할 것 같다.