예술성 [2022-상반기 오후 2번 문제]

문제 링크

삼성 코딩테스트 기출 문제: 예술성 - 코드트리
주요 IT 기업의 코딩테스트 기출 문제를 연습하며 실전 감각을 키우세요. 취업 합격률을 높이는 필수 연습 과정입니다.

문제 설명

n*n의 격자가 있음. 1-10의 숫자가 써져있음.

같은 숫자로 인접한 경우 하나의 그룹으로 봄.

각 턴 당 점수를 얻는데, a,b라고 한다면

(a의 갯수 + b의 갯수) * a값 * b값 * 서로 맞닿아있는 변의 수를 점수로 침.

그 후, 회전을 진행하는데, 십자를 기준으로 십자는 반시계 방향으로 회전하고, 십자를 제외한 정사각형은 시계방향으로 90도 회전함.

4번의 턴 이후의 점수를 구하기.

해결 방법

회전십자 따로, 정사각형 따로 회전시켜줬음.

int calculate_art_val() {
	int ret = 0;
	for (int i = 0;i < group.size();i++) {
		for (int j = i+1;j < group.size();j++) {
			int adj_val = get_adjust_val(i, j);
			if (adj_val == 0) continue;
			int val = (group[i].cnt + group[j].cnt) * group[i].val * group[j].val * adj_val;
			ret += val;
		}
	}

	return ret;
}

int tmp_arr[30][30];

void rotate() {
	int ttmp[30][30];
	int N = n / 2;

	for (int i = 0;i < N;i++) {
		for (int j = 0;j < N;j++) {
			ttmp[i][j] = tmp_arr[N-j-1][i];
		}
	}

	for (int i = 0;i < N;i++) {
		for (int j = 0;j < N;j++) {
			tmp_arr[i][j] = ttmp[i][j];
		}
	}
}

void rotate_arr() {
	int N = n / 2;

	memset(tmp_arr, 0, sizeof(tmp_arr));
	// 1. tmp_arr에 넣기 -> 돌리기 -> 다시 복귀

	int dtx[4] = { 0,N+1,0,N+1 };
	int dty[4] = { 0,0,N+1,N+1 };

	for (int t = 0;t < 4;t++) {
		for (int i = 0;i < N;i++) {
			for (int j = 0;j < N;j++) {
				tmp_arr[i][j] = arr[i+dtx[t]][j+dty[t]];
			}
		}
		rotate();
		for (int i = 0;i < N;i++) {
			for (int j = 0;j < N;j++) {
				arr[i+dtx[t]][j+dty[t]] = tmp_arr[i][j];
			}
		}
	}

	int ttmp[2][31];
	for (int i = 0;i < n;i++) {
		ttmp[0][n-1-i] = arr[N][i];
	}
	
	for (int i = 0;i < n;i++) {
		ttmp[1][i] = arr[i][N];
	}

	for (int i = 0;i < n;i++) {
		arr[N][i] = ttmp[1][i];
		arr[i][N] = ttmp[0][i];
	}
}

점수 계산점수를 계산해주는데, 인접한 변을 계산하기 위해서 BFS를 사용하여 인접한 값들을 중복으로 세줬음.

int adjust_visited[31][31];
int get_adjust_val(int t1, int t2) {
	int v1, v2;
	v1 = t1+1; v2 = t2+1;

	memset(adjust_visited, 0, sizeof(adjust_visited));
	int x, y;
	x = group[t1].x, y = group[t1].y;

	queue<pair<int, int>> que;
	adjust_visited[x][y] = 1;

	int cx, cy, nx, ny;
	int ret_val = 0;
	que.push({ x,y });
	while (!que.empty()) {
		tie(cx, cy) = que.front();
		que.pop();

		for (int i = 0;i < 4;i++) {
			nx = cx + dx[i], ny = cy + dy[i];
			if (nx < 0 || ny < 0 || nx >= n || ny >= n) continue;
			if (adjust_visited[nx][ny] != 0) continue;
			if (visited[nx][ny] == v1) {
				// 본인인 경우
				adjust_visited[nx][ny] = 1;
				que.push({ nx,ny });
			}
			else if (visited[nx][ny] == v2) {
				ret_val++;
			}
		}
	}

	return ret_val;
}

int calculate_art_val() {
	int ret = 0;
	for (int i = 0;i < group.size();i++) {
		for (int j = i+1;j < group.size();j++) {
			int adj_val = get_adjust_val(i, j);
			if (adj_val == 0) continue;
			int val = (group[i].cnt + group[j].cnt) * group[i].val * group[j].val * adj_val;
			ret += val;
		}
	}

	return ret;
}

그룹 지어주기각 그룹의 첫번째 인덱스와 갯수, 그리고 값을 벡터에 저장해줌.

int set_group(int x,int y,int val) {
	int ret = 1;
	queue<pair<int, int>> que;
	que.push({ x,y });
	visited[x][y] = val;

	int cx, cy, nx, ny;
	while (!que.empty()) {
		tie(cx, cy) = que.front();
		que.pop();

		for (int i = 0;i < 4;i++) {
			nx = cx + dx[i], ny = cy + dy[i];
			if (nx < 0 || ny < 0 || nx >= n || ny >= n) continue;
			if (visited[nx][ny] != 0) continue;
			if (arr[nx][ny] != arr[x][y]) continue;
			visited[nx][ny] = val;
			ret++;
			que.push({ nx,ny });
		}
	}

	return ret;
}

void make_group() {
	memset(visited, 0, sizeof(visited));
	
	vector<_group> vec;
	for (int i = 0;i < n;i++) {
		for (int j = 0;j < n;j++) {
			if (visited[i][j] == 0) {
				_group tmp;
				int val = vec.size() + 1;
				tmp.cnt = set_group(i, j,val);
				tmp.x = i, tmp.y = j;
				tmp.val = arr[i][j];
				vec.push_back(tmp);
			}
		}
	}	
	group = vec;
}

전체 코드

#include <iostream>
#include <vector>
#include <tuple>
#include <queue>
#include <cstring>

using namespace std;

typedef struct {
	int x, y;
	int cnt;
	int val;
}_group;

int n;
int arr[31][31];
int visited[31][31];
int dx[4] = { -1,1,0,0 };
int dy[4] = { 0,0,-1,1 };
vector<_group> group;

void input() {
	cin >> n;
	for (int i = 0;i < n;i++) {
		for (int j = 0;j < n;j++) {
			cin >> arr[i][j];
		}
	}
}

int set_group(int x,int y,int val) {
	int ret = 1;
	queue<pair<int, int>> que;
	que.push({ x,y });
	visited[x][y] = val;

	int cx, cy, nx, ny;
	while (!que.empty()) {
		tie(cx, cy) = que.front();
		que.pop();

		for (int i = 0;i < 4;i++) {
			nx = cx + dx[i], ny = cy + dy[i];
			if (nx < 0 || ny < 0 || nx >= n || ny >= n) continue;
			if (visited[nx][ny] != 0) continue;
			if (arr[nx][ny] != arr[x][y]) continue;
			visited[nx][ny] = val;
			ret++;
			que.push({ nx,ny });
		}
	}

	return ret;
}

void make_group() {
	memset(visited, 0, sizeof(visited));
	
	vector<_group> vec;
	for (int i = 0;i < n;i++) {
		for (int j = 0;j < n;j++) {
			if (visited[i][j] == 0) {
				_group tmp;
				int val = vec.size() + 1;
				tmp.cnt = set_group(i, j,val);
				tmp.x = i, tmp.y = j;
				tmp.val = arr[i][j];
				vec.push_back(tmp);
			}
		}
	}	
	group = vec;
}

int adjust_visited[31][31];
int get_adjust_val(int t1, int t2) {
	int v1, v2;
	v1 = t1+1; v2 = t2+1;

	memset(adjust_visited, 0, sizeof(adjust_visited));
	int x, y;
	x = group[t1].x, y = group[t1].y;

	queue<pair<int, int>> que;
	adjust_visited[x][y] = 1;

	int cx, cy, nx, ny;
	int ret_val = 0;
	que.push({ x,y });
	while (!que.empty()) {
		tie(cx, cy) = que.front();
		que.pop();

		for (int i = 0;i < 4;i++) {
			nx = cx + dx[i], ny = cy + dy[i];
			if (nx < 0 || ny < 0 || nx >= n || ny >= n) continue;
			if (adjust_visited[nx][ny] != 0) continue;
			if (visited[nx][ny] == v1) {
				// 본인인 경우
				adjust_visited[nx][ny] = 1;
				que.push({ nx,ny });
			}
			else if (visited[nx][ny] == v2) {
				ret_val++;
			}
		}
	}

	return ret_val;
}

int calculate_art_val() {
	int ret = 0;
	for (int i = 0;i < group.size();i++) {
		for (int j = i+1;j < group.size();j++) {
			int adj_val = get_adjust_val(i, j);
			if (adj_val == 0) continue;
			int val = (group[i].cnt + group[j].cnt) * group[i].val * group[j].val * adj_val;
			ret += val;
		}
	}

	return ret;
}

int tmp_arr[30][30];

void rotate() {
	int ttmp[30][30];
	int N = n / 2;

	for (int i = 0;i < N;i++) {
		for (int j = 0;j < N;j++) {
			ttmp[i][j] = tmp_arr[N-j-1][i];
		}
	}

	for (int i = 0;i < N;i++) {
		for (int j = 0;j < N;j++) {
			tmp_arr[i][j] = ttmp[i][j];
		}
	}
}

void rotate_arr() {
	int N = n / 2;

	memset(tmp_arr, 0, sizeof(tmp_arr));
	// 1. tmp_arr에 넣기 -> 돌리기 -> 다시 복귀

	int dtx[4] = { 0,N+1,0,N+1 };
	int dty[4] = { 0,0,N+1,N+1 };

	for (int t = 0;t < 4;t++) {
		for (int i = 0;i < N;i++) {
			for (int j = 0;j < N;j++) {
				tmp_arr[i][j] = arr[i+dtx[t]][j+dty[t]];
			}
		}
		rotate();
		for (int i = 0;i < N;i++) {
			for (int j = 0;j < N;j++) {
				arr[i+dtx[t]][j+dty[t]] = tmp_arr[i][j];
			}
		}
	}

	int ttmp[2][31];
	for (int i = 0;i < n;i++) {
		ttmp[0][n-1-i] = arr[N][i];
	}
	
	for (int i = 0;i < n;i++) {
		ttmp[1][i] = arr[i][N];
	}

	for (int i = 0;i < n;i++) {
		arr[N][i] = ttmp[1][i];
		arr[i][N] = ttmp[0][i];
	}
}

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);

//	freopen("sample_input.txt", "r", stdin);

	input();

	int result = 0;

	for (int i = 0;i <= 3;i++) {ㄱ
		make_group();
		result += calculate_art_val();
		rotate_arr();
	}
	cout << result;
}