슈뢰딩거의 고등어

21608 상어초등학교 본문

알고리즘

21608 상어초등학교

슈뢰딩거의 고등어 2021. 12. 11. 02:22

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

 

21608번: 상어 초등학교

상어 초등학교에는 교실이 하나 있고, 교실은 N×N 크기의 격자로 나타낼 수 있다. 학교에 다니는 학생의 수는 N2명이다. 오늘은 모든 학생의 자리를 정하는 날이다. 학생은 1번부터 N2번까지 번호

www.acmicpc.net

 

실버 1

 

#include <iostream>
#include <vector>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;

const int dy[4] = {-1, 0, 0, 1};
const int dx[4] = {0, -1, 1, 0};

struct Student {
	int no;
	int y, x;
	int friends[4];
};

int n, answer;
int arr[21][21];
vector <Student> st;

// 구현
// return how many close friend in y, x
int count_friend(int std_no, int y, int x) {

	int result = 0;
	for(int i=0; i<4; i++) {
		int ny = y + dy[i];
		int nx = x + dx[i];

		if(ny < 0 || ny >= n || nx < 0 || nx >= n)
			continue;

		if (arr[ny][nx] == -1)
			continue;

		for(int f=0; f<4; f++) {
			int friend_no = arr[ny][nx];
			if (friend_no == st[std_no].friends[f]) {
				result++;
			}
		}

	}
	return result;

}


// return how many blank near y, x
int count_blank(int y, int x) {

	int result = 0;
	for(int i=0; i<4; i++) {
		int ny = y + dy[i];
		int nx = x + dx[i];

		if(ny < 0 || ny >= n || nx < 0 || nx >= n)
			continue;
		
		if(arr[ny][nx] == -1)
			result++;

	}
	return result;

}

bool compare (pair<int, int> a, pair<int, int> b) {

	if(a.first == b.first)
		return a.second < b.second;

	return a.first < b.first;

}



void solve() {

	// init 
	memset(arr, -1, sizeof(arr));

	for(int s=0; s<st.size(); s++) {
		int student_no = st[s].no;
		int tmp_arr[n][n];

		// copy 때려주기
		for(int i=0; i<n; i++)
			for(int j=0; j<n; j++){
				tmp_arr[i][j] = arr[i][j];
			}

		// check map
		int max_f_value = -1;
		vector <pair<int, int>> v;

		for(int i=0; i<n; i++)
			for(int j=0; j<n; j++) {

				// if not empty skip!
				if(tmp_arr[i][j] != -1)
					continue;

				// case1 > 친구인접 최대 위치 max_y, max_x
				tmp_arr[i][j] = count_friend(s, i, j);
				if(tmp_arr[i][j] > max_f_value) {
					v.clear(); // 초기화
					v.push_back(make_pair(i, j));
					max_f_value = tmp_arr[i][j];
				}
				else if(tmp_arr[i][j] == max_f_value) {
					v.push_back(make_pair(i, j));
				}

			}


		// case 1
		if (v.size() == 1) {
			arr[v[0].first][v[0].second] = student_no;
			st[s].y = v[0].first;
			st[s].x = v[0].second;
			continue;
		}
		int v_size = v.size();
		int max_blank = -1;
		vector <pair<int, int>> b;
		// 인접빈칸개수
		for(int i=0; i<v.size(); i++) {
			int cy = v[i].first;
			int cx = v[i].second;

			int tmp_blank = count_blank(cy, cx);

			if(tmp_blank > max_blank) {
				max_blank = tmp_blank;
				b.clear();
				b.push_back(make_pair(cy, cx));
			}
			else if(tmp_blank == max_blank) {
				b.push_back(make_pair(cy, cx));
			}

		}

		// case 2
		if(b.size() == 1) {
			arr[b[0].first][b[0].second] = student_no;
			st[s].y = b[0].first;
			st[s].x = b[0].second;
			continue;
		} 

		sort(b.begin(), b.end(), compare);

		// case 3
		arr[b[0].first][b[0].second] = student_no;
		st[s].y = b[0].first;
		st[s].x = b[0].second;

	}


}


void calculate() {

	for(int i=0; i<n*n; i++) {
		//int std_no = st[i].no;
		int cy = st[i].y;
		int cx = st[i].x;

		int f_cnt = count_friend(i, cy, cx);

		f_cnt = pow(10, (f_cnt-1));
		if (f_cnt >= 1)
			answer += f_cnt;
	}
}


int main() {

	scanf("%d", &n);

	for(int i=0; i<n*n; i++) {
		Student tmp;
		int a, b, c, d, e;
		scanf("%d %d %d %d %d", &a, &b, &c, &d, &e);
		a--; b--; c--; d--; e--;

		tmp.no = a;
		tmp.friends[0] = b;
		tmp.friends[1] = c;
		tmp.friends[2] = d;
		tmp.friends[3] = e;
		st.push_back(tmp);
	}


	solve();
	
	calculate();

	printf("%d\n", answer);

	return 0;
}

 

 

코드 설명

const int dy[4] = {-1, 0, 0, 1};
const int dx[4] = {0, -1, 1, 0};

struct Student {
	int no;
	int y, x;
	int friends[4];
};

int n, answer;
int arr[21][21];
vector <Student> st;

Student 구조체로 학생번호, 위치, 친구 정보 저장 vector 로 동적

 

int main() {

	scanf("%d", &n);

	for(int i=0; i<n*n; i++) {
		Student tmp;
		int a, b, c, d, e;
		scanf("%d %d %d %d %d", &a, &b, &c, &d, &e);
		a--; b--; c--; d--; e--; // 학생번호 0 부터 시작하도록 각  -- 해줌

		tmp.no = a;
		tmp.friends[0] = b;
		tmp.friends[1] = c;
		tmp.friends[2] = d;
		tmp.friends[3] = e;
		st.push_back(tmp);
	}


	solve(); //각 학생 배치
	
	calculate(); // 점수 계산

	printf("%d\n", answer);

	return 0;

 

void solve() {

	// init 
	memset(arr, -1, sizeof(arr)); // 초기 맵 -1 로 초기화 해줌 (학생 번호를 0 부터 시작하도록 했기 때문)

	/**************************************************************/
	for(int s=0; s<st.size(); s++) {
		int student_no = st[s].no; // 학생 번호
		int tmp_arr[n][n]; // 1번조건에서 사용할 임시 맵

		// arr -> tmp_arr 로 copy
		for(int i=0; i<n; i++)
			for(int j=0; j<n; j++){
				tmp_arr[i][j] = arr[i][j];
			}
	
		int max_f_value = -1; // 최대친구수 저장할 변수
		vector <pair<int, int>> v; // 최대친구수를 얻을수 있는 좌표를 저장

		for(int i=0; i<n; i++)
			for(int j=0; j<n; j++) {

				// if not empty skip!
				if(tmp_arr[i][j] != -1)
					continue;

				// s 의 친구 수 세기 (i,j) 위치에서
				tmp_arr[i][j] = count_friend(s, i, j);
                
                // 더 많은 친구를 만날수 있는 위치가 존재한다면
				if(tmp_arr[i][j] > max_f_value) {
					v.clear(); // 초기화
					v.push_back(make_pair(i, j)); // 위치 집어넣기
					max_f_value = tmp_arr[i][j]; // 최대 친구수 변경
				}
                // 최대친구수와 동일할 경우
				else if(tmp_arr[i][j] == max_f_value) {
					v.push_back(make_pair(i, j)); // 위치 집어넣기
				}

			}


		// case 1 : 배치
		if (v.size() == 1) {
			arr[v[0].first][v[0].second] = student_no;
			st[s].y = v[0].first;
			st[s].x = v[0].second;
			continue;
		}
        
        /**************************************************************/
		int max_blank = -1;
		vector <pair<int, int>> b;
		// 인접빈칸개수 -> 위와 동일 로직
		for(int i=0; i<v.size(); i++) {
			int cy = v[i].first;
			int cx = v[i].second;

			int tmp_blank = count_blank(cy, cx);

			if(tmp_blank > max_blank) {
				max_blank = tmp_blank;
				b.clear();
				b.push_back(make_pair(cy, cx));
			}
			else if(tmp_blank == max_blank) {
				b.push_back(make_pair(cy, cx));
			}

		}

		// case 2 : 배치
		if(b.size() == 1) {
			arr[b[0].first][b[0].second] = student_no;
			st[s].y = b[0].first;
			st[s].x = b[0].second;
			continue;
		} 
        
		/**************************************************************/
		sort(b.begin(), b.end(), compare); // 정렬, 맨 처음 오는 value 로 배치하면 된다.

		// case 3 : 배치
		arr[b[0].first][b[0].second] = student_no;
		st[s].y = b[0].first;
		st[s].x = b[0].second;

	}


}
// return how many close friend in y, x
int count_friend(int std_idx, int y, int x) {

	int result = 0;
	for(int i=0; i<4; i++) {
		int ny = y + dy[i];
		int nx = x + dx[i];
		
        // 배열 밖일 경우 continue
		if(ny < 0 || ny >= n || nx < 0 || nx >= n)
			continue;
		
        // 빈칸일 경우 continue
		if (arr[ny][nx] == -1)
			continue;

		for(int f=0; f<4; f++) {
			int friend_no = arr[ny][nx];
            // 	친구번호 존재할 경우 ++
			if (friend_no == st[std_idx].friends[f]) {
				result++;
			}
		}

	}
	return result;

}
int count_blank(int y, int x) {

	int result = 0;
	for(int i=0; i<4; i++) {
		int ny = y + dy[i];
		int nx = x + dx[i];

		if(ny < 0 || ny >= n || nx < 0 || nx >= n)
			continue;
		
		if(arr[ny][nx] == -1)
			result++;

	}
	return result;
bool compare (pair<int, int> a, pair<int, int> b) {

	if(a.first == b.first)
		return a.second < b.second;

	return a.first < b.first;

}
void calculate() {

	for(int i=0; i<n*n; i++) {
		int cy = st[i].y;
		int cx = st[i].x;

		int f_cnt = count_friend(i, cy, cx);

		f_cnt = pow(10, (f_cnt-1)); // 10^(f_cnt-1)
		if (f_cnt >= 1)
			answer += f_cnt;
	}
}

 

 

초기 틀렸던 이유!

학생의 번호와 Vector <Student> std 의 인덱스가 다른 개념임.

이걸 동일시 해서 틀림

'알고리즘' 카테고리의 다른 글

13460 구슬탈출2  (0) 2021.12.19
21609 상어중학교  (0) 2021.12.13
14888 연산자 끼워넣기 ( DFS : 중복순열 || next_permutation)  (0) 2021.12.10
17143 낚시왕  (0) 2021.12.09
19237 어른상어  (0) 2021.12.08
Comments