2025. 4. 15. 17:51ㆍ카테고리 없음
정확히는 기억이 안나지만 대충 이런느낌
N x N 맵에서 T 만큼 실행 횟수를 진행 함
N x N 맵에는 각 칸에 해당하는 색상(RGB)와 에너지값을 입력받음
인접한 같은 색상에 대해서는 군집을 형성함
그리고 실행 횟수만큼 다음을 반복함
1. 모든 칸의 에너지 값을 1 증가시킨다.
2. 각 군집에서 우두머리를 정한다, 가장 큰 에너지 값을 가진 칸이 우두머리가 되고 여러 칸이 존재 할 시 더 낮은 col 그리고 더 낮은 row 에 해당하는 칸이 우두머리가 된다. 그리고 각 군집에 대한 우두머리는 공격권을 가지고 에너지 순서 그리고 더 낮은 col, row 로 순서대로 공격을 진행한다.
3. 공격을 하는것은 에너지를 4로 나누었을때 나머지 값으로 방향이 결정된다. 나머지 0, 1, 2, 3 -> 위, 아래, 왼쪽, 오른쪽. 공격의 세기는 에너지 값 - 1 이 되고 공격한 뒤에는 에너지가 1이 된다. 공격 방향에 해당하는 칸이 같은 색일 경우 다음칸으로 넘어간다 (공격이 맵을 벗어나는 경우 없어짐). 공격당하는 색이 공격하는 색과 다를 경우, 두가지 방향으로 진행이 된다. 첫번째는 공격의 세기가 공격받는 칸보다 클 경우 공격의 세기는 공격받는 칸 + 1 만큼 감소하고 공격받는 칸은 에너지가 + 1 이 되고 공격에 대한 색으로 변하고 다음칸으로 공격이 계속된다. (예를들어 초록색에 대한 10의 공격이 빨간색 3 이 받는다면 빨간색 칸은 초록색 4로 변하고 공격의 세기는 6으로 변한다) 두번째 공격의 세기가 공격받는 칸보다 작을 경우 공격받는 칸의 색은 공격하는 색과 합쳐지고 에너지도 합쳐지는 유전자 변이 현상이 일어난다 (예를들어 초록색에 대한 5의 공격이 빨간색 7이 받는다면 에너지 12의 노랑색이 만들어진다). 이를 모든 우두머리가 공격을 진행할때까지 반복한다, 여기서 해당 우두머리가 이전의 우두머리의 공격에 의해서 유전자 변이가 일어난다면 공격권은 없어진다.
4. 이러한 과정을 반복한다.
최종적으로 출력하는 결과는 각 색깔의 모든 에너지 값의 합이다 (R, G, B, Y, C, M, W)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX 50 // 최대 맵 크기 (50x50)
#define COLOR_CNT 7 // 색상 종류 수: R, G, B, Y, C, M, W
// 하나의 셀: 색과 에너지를 가짐
typedef struct {
int color;
int energy;
} Cell;
// 좌표 저장용 구조체
typedef struct {
int x, y;
} Coord;
int N, T; // 맵 크기 N, 실행 횟수 T
Cell map[MAX][MAX]; // 전체 맵
int dx[4] = {-1, 1, 0, 0}; // 방향: 위, 아래, 왼, 오른
int dy[4] = {0, 0, -1, 1};
int color_energy[COLOR_CNT]; // 각 색상별 최종 에너지 총합 저장
// 색상 문자 인덱싱용 배열 (출력 시 사용)
char color_char[] = {'R', 'G', 'B', 'Y', 'C', 'M', 'W'};
// 색상 문자 → 정수 인덱스로 변환
int color_index(char c) {
switch(c) {
case 'R': return 0;
case 'G': return 1;
case 'B': return 2;
case 'Y': return 3;
case 'C': return 4;
case 'M': return 5;
case 'W': return 6;
}
return -1;
}
// 유전자 융합: 두 색을 섞었을 때 결과 색 결정
int mix_colors(int c1, int c2) {
if ((c1 == 0 && c2 == 1) || (c1 == 1 && c2 == 0)) return 3; // R+G = Y
if ((c1 == 0 && c2 == 2) || (c1 == 2 && c2 == 0)) return 4; // R+B = C
if ((c1 == 1 && c2 == 2) || (c1 == 2 && c2 == 1)) return 5; // G+B = M
return 6; // 나머지는 W
}
// BFS 방문 확인 배열
int visited[MAX][MAX];
// BFS 큐
Coord queue[MAX * MAX];
int front, rear;
// 방문 배열 초기화
void reset_visited() {
memset(visited, 0, sizeof(visited));
}
// 우두머리 우선순위 비교: 에너지 높음 > 열 작음 > 행 작음
int compare_leader(const void* a, const void* b) {
Coord* A = (Coord*)a;
Coord* B = (Coord*)b;
int ea = map[A->x][A->y].energy;
int eb = map[B->x][B->y].energy;
if (ea != eb) return eb - ea;
if (A->y != B->y) return A->y - B->y;
return A->x - B->x;
}
// 군집 내 우두머리를 찾고 leaders 배열에 추가
void find_leaders(Coord* leaders, int* leader_count) {
*leader_count = 0;
reset_visited();
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (visited[i][j]) continue;
int color = map[i][j].color;
Coord best = (Coord){i, j}; // 초기 우두머리 후보
front = rear = 0;
queue[rear++] = (Coord){i, j};
visited[i][j] = 1;
// BFS 시작
while (front < rear) {
Coord cur = queue[front++];
// 우두머리 갱신 조건
if (map[cur.x][cur.y].energy > map[best.x][best.y].energy ||
(map[cur.x][cur.y].energy == map[best.x][best.y].energy &&
(cur.y < best.y || (cur.y == best.y && cur.x < best.x)))) {
best = cur;
}
// 상하좌우 같은 색으로 확장
for (int d = 0; d < 4; d++) {
int nx = cur.x + dx[d];
int ny = cur.y + dy[d];
if (nx >= 0 && ny >= 0 && nx < N && ny < N &&
!visited[nx][ny] && map[nx][ny].color == color) {
visited[nx][ny] = 1;
queue[rear++] = (Coord){nx, ny};
}
}
}
// 우두머리 추가
leaders[(*leader_count)++] = best;
}
}
}
// 시뮬레이션 로직 전체 실행
void simulate() {
for (int step = 0; step < T; step++) {
// Step 1: 에너지 +1
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
map[i][j].energy++;
// Step 2: 군집 우두머리 찾고 정렬
Coord leaders[MAX * MAX];
int leader_count = 0;
find_leaders(leaders, &leader_count);
qsort(leaders, leader_count, sizeof(Coord), compare_leader);
int attacked[MAX][MAX] = {0}; // 이미 행동한 우두머리 기록
// Step 3: 모든 우두머리 공격 실행
for (int i = 0; i < leader_count; i++) {
Coord l = leaders[i];
if (attacked[l.x][l.y]) continue; // 이미 변화되면 스킵
int c = map[l.x][l.y].color;
int e = map[l.x][l.y].energy;
int atk = e - 1;
int dir = e % 4;
// 에너지 초기화 및 공격 시작
map[l.x][l.y].energy = 1;
attacked[l.x][l.y] = 1;
int x = l.x + dx[dir], y = l.y + dy[dir];
while (x >= 0 && y >= 0 && x < N && y < N && atk > 0) {
if (map[x][y].color == c) {
// 같은 색이면 건너뜀
x += dx[dir];
y += dy[dir];
continue;
}
if (atk > map[x][y].energy) {
// 공격력이 더 크면 점령
atk -= map[x][y].energy;
map[x][y].color = c;
map[x][y].energy = atk + 1;
attacked[x][y] = 1;
x += dx[dir];
y += dy[dir];
} else {
// 유전자 융합
int mixed = mix_colors(c, map[x][y].color);
map[x][y].color = mixed;
map[x][y].energy += atk;
attacked[x][y] = 1;
break;
}
}
}
}
}
// 메인 함수
int main() {
scanf("%d %d", &N, &T);
// 입력: 색 + 에너지
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++) {
char sc;
int e;
scanf(" %c%d", &sc, &e);
map[i][j].color = color_index(sc);
map[i][j].energy = e;
}
simulate(); // 시뮬레이션 실행
// 최종 색상별 에너지 총합 계산
memset(color_energy, 0, sizeof(color_energy));
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
color_energy[map[i][j].color] += map[i][j].energy;
// 출력: R G B Y C M W 순서
for (int i = 0; i < COLOR_CNT; i++)
printf("%d ", color_energy[i]);
printf("\n");
return 0;
}
해당 포스팅은 경험을 남기기 위함이고 상업적, 영리적 의도는 없음을 밝힙니다.