알고리즘/[ADV] 삼성 SW 역량 테스트 A형
[코드트리] Sam의 피자학교 (삼성 SW 역량테스트 2021 하반기 오후 2번)
피로물든딸기
2024. 6. 9. 00:57
반응형
https://www.codetree.ai/training-field/frequent-problems/problems/sam-pizza-school
Sam의 피자학교 문제 풀이는 BOJ 23291 : 어항 정리와 같다.
#include <stdio.h>
#define MAX (100 + 10)
int T;
int N, K;
int pizza[MAX][MAX];
/* 순서대로 오른쪽 : 1, 왼쪽 : 2, 위 : 3, 아래 : 4 */
int dr[] = { 0, 0, 0, -1, 1 };
int dc[] = { 0, 1, -1, 0, 0 };
void input()
{
scanf("%d %d", &N, &K);
for (int i = 0; i < MAX; i++)
for (int k = 0; k < MAX; k++)
pizza[i][k] = 0;
for (int i = 1; i <= N; i++)
{
int f;
scanf("%d", &f);
pizza[N][i] = f;
}
}
void output(int n)
{
for (int r = 1; r <= N; r++)
{
for (int c = 1; c <= N; c++)
printf("%2d ", pizza[r][c]);
putchar('\n');
}
putchar('\n');
}
void addFlour()
{
int min = 0x7fff0000;
for (int r = 1; r <= N; r++)
{
for (int c = 1; c <= N; c++)
{
if (pizza[r][c] == 0) continue;
if (pizza[r][c] < min) min = pizza[r][c];
}
}
for (int r = 1; r <= N; r++)
for (int c = 1; c <= N; c++)
if (pizza[r][c] == min) pizza[r][c]++;
}
void move()
{
int start, width, height;
start = width = height = 1;
int i = 0;
while (1)
{
if (start + width + height - 1 > N) break;
for (int c = start; c < start + width; c++)
{
for (int r = N; r > N - height; r--)
{
int nr, nc;
nr = N - width + c - start;
nc = start + width + N - r;
pizza[nr][nc] = pizza[r][c];
pizza[r][c] = 0;
}
}
if (i % 2) width++;
else height++;
start += (i / 2 + 1);
i++;
}
}
void sperad()
{
int tmppizza[MAX][MAX] = { 0 };
for (int r = 1; r <= N; r++)
{
for (int c = 1; c <= N; c++)
{
if (pizza[r][c] > 0)
{
int save = pizza[r][c];
for (int dir = 1; dir <= 4; dir++)
{
int nr, nc;
nr = r + dr[dir];
nc = c + dc[dir];
if (pizza[nr][nc] == 0) continue;
if (pizza[r][c] > pizza[nr][nc]) // 물고기가 많은 경우만 이동
{
int diff = (pizza[r][c] - pizza[nr][nc]) / 5;
save -= diff;
tmppizza[nr][nc] += diff;
}
}
tmppizza[r][c] += save;
}
}
}
for (int r = 1; r <= N; r++)
for (int c = 1; c <= N; c++)
pizza[r][c] = tmppizza[r][c];
}
void pizzaSort()
{
int idx;
int tmppizza[MAX][MAX] = { 0 };
idx = 1;
for (int c = 1; c <= N; c++)
{
if (pizza[N][c] == 0) continue;
int row = N;
while (1)
{
if (pizza[row][c] == 0) break;
tmppizza[N][idx++] = pizza[row][c];
row--;
}
}
for (int r = 1; r <= N; r++)
for (int c = 1; c <= N; c++)
pizza[r][c] = tmppizza[r][c];
}
void fold()
{
int sc = N / 2 + 1;
for (int c = N / 2; c >= 1; c--) pizza[N - 1][sc++] = pizza[N][c];
for (int c = N / 2; c >= 1; c--) pizza[N][c] = 0;
for (int r = N - 1; r <= N; r++)
{
int ec = N / 4 * 3;
int fix = N;
for (int c = N / 2 + 1; c <= ec; c++)
{
int nr, nc;
nr = 2 * N - r - 3;
nc = fix--;
pizza[nr][nc] = pizza[r][c];
pizza[r][c] = 0;
}
}
}
int check()
{
int max = 0;
int min = 0x7fff0000;
for (int r = 1; r <= N; r++)
{
for (int c = 1; c <= N; c++)
{
if (pizza[r][c] == 0) continue;
if (pizza[r][c] < min) min = pizza[r][c];
if (pizza[r][c] > max) max = pizza[r][c];
}
}
if (max - min <= K) return 1;
return 0;
}
int main(void)
{
// scanf("%d", &T);
T = 1;
for (int tc = 1; tc <= T; tc++)
{
input();
int count = 0;
while (1)
{
addFlour();
move();
sperad();
pizzaSort();
fold();
sperad();
pizzaSort();
count++;
if (check()) break;
}
printf("%d\n", count);
}
return 0;
}
반응형