www.acmicpc.net/problem/17825

 

17825번: 주사위 윷놀이

첫째 줄에 주사위에서 나올 수 10개가 순서대로 주어진다.

www.acmicpc.net

1. 풀이방법

- 쉽다고 생각하면서 , 시작해서 개고생하며 어렵게 끝낸 문제입니다.....

 

- 첫번째 문제점, 30 노드가 중복되는 것을 체크하지 못한점.

 

- 30 노드에 도착하면 방향을 바꾸도록 설정했다가 다른 30 (끝 쪽에 가까운) 거기에 말들이 도착헀을때도 방향을 바꾸는 현상 발생.

 

- 두번째 문제점, 방문체크를 할때 여러개 있는 노드들을 고려하지 않은 것.

 

- 문제를 보면, 두개이상 존재하는 노드들이 있다 (16, 22,28,30.....)

 

- 결국 현재 말들의 위치만을 비교함으로써 겹쳐지는지 아닌지 알 수 가 없다.

 

- 결국 코드를 싹 지우고, 다시 짜면서 해결한 방법은

 

- 각각 고유의 번호를 가지는 노드들로 같은 모양의 그래프를 만들어 준 후, 문제에서의 노드들은 점수들로서

 

- 매칭을 시켜주었습니다. 그러면 첫, 두 번째 문제점들이 모두 해결됩니다.

 

- 그림을 보시면 아이디어를 이해하시기 편할 겁니다.

 

- 전체적인 문제해결은 dfs를 이용한 완전탐색 입니다.

 

 

 

2. 주의사항

- 일단 코드를 작성하기 전, 문제를 항상 정확히 파악하고 시작하고자 노력하지만

 

- 이 문제처럼, 처음 시작할 때 발생하는 문제를 예상하지 못하고 시작하면 굉장히 어려워 지고 꼬입니다....

 

- 역시, 주의사항은...... 문제를 꼼꼼히 잘 분석하자......

 

 

3. 나의코드

#include<bits/stdc++.h>
using namespace std;

// 시작노드 0, 도착점 노드 21
int route[4][33];
int score[33]; // 점수계산을 위한 노드
int maxresult;
int inputnum[10];
pair<int, int> ob[4]; //4개의말 (현재위치, 타고있는 방향)

void inputs() {
	for (int i = 0; i < 10; i++) {
		cin >> inputnum[i];
	}
}
void setscore() {
	for (int i = 1; i <= 20; i++) {
		score[i] = 2 * i;
	}
	score[22] = 13; score[23] = 16; score[24] = 19;
	score[25] = 25; score[30] = 26; score[29] = 27;
	score[28] = 28; score[26] = 22; score[27] = 24;
	score[31] = 30; score[32] = 35; score[21] = 0;
}
void makegraph() {
	for (int i = 0; i < 21; i++) {
		route[0][i] = i + 1;
	}
	route[0][21] = 21;
	route[1][5] = 22; route[1][22] = 23; route[1][23] = 24;
	route[1][24] = 25; route[1][25] = 31; route[1][31] = 32;
	route[1][32] = 20; route[1][20] = 21; route[1][21] = 21;
	route[2][10] = 26; route[2][26] = 27; route[2][27] = 25;
	route[2][25] = 31; route[2][31] = 32; route[2][32] = 20;
	route[2][20] = 21; route[2][21] = 21;
	route[3][15] = 28; route[3][28] = 29; route[3][29] = 30;
	route[3][30] = 25; route[3][25] = 31; route[3][31] = 32;
	route[3][32] = 20; route[3][20] = 21; route[3][21] = 21;
}
bool existcheck(int s,int index) {
	if (s == 21) return false;
	for (int i = 0; i < 4; i++) {
		if (i == index) continue;
		if (ob[i].first == 21) continue;
		if (ob[i].first == s) return true;
	}
	return false;
}
void makecase(int cnt,int resultsum) {
	if (cnt == 10) {
		maxresult = max(resultsum, maxresult);
		return;
	}
	int thisnum = inputnum[cnt];
	for (int i = 0; i < 4; i++) {
		if (ob[i].first == 21) continue; //이미 도착점에 있는 말
		int prevnum = ob[i].first;
		int prevdir = ob[i].second;
		for (int j = 0; j < thisnum; j++) {
			ob[i].first = route[prevdir][ob[i].first];
		}
		if (ob[i].first == 5) ob[i].second = 1;
		if (ob[i].first == 10) ob[i].second = 2;
		if (ob[i].first == 15) ob[i].second = 3;

		if (!existcheck(ob[i].first,i)) {
			makecase(cnt + 1, resultsum + score[ob[i].first]);
		}
		ob[i].first = prevnum;
		ob[i].second = prevdir;

	}
}
int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	inputs();
	setscore();
	makegraph();
	makecase(0,0);
	cout << maxresult;
	return 0;
}

'알고리즘 문제풀이 > 구현' 카테고리의 다른 글

백준 17143 [C++]  (0) 2021.03.08
백준 17822 [C++]  (0) 2021.03.08
백준 17837 [C++]  (0) 2021.03.06
백준 16235 [C++]  (0) 2021.03.06
백준 17779 [C++]  (0) 2021.03.05

www.acmicpc.net/problem/16235

 

16235번: 나무 재테크

부동산 투자로 억대의 돈을 번 상도는 최근 N×N 크기의 땅을 구매했다. 상도는 손쉬운 땅 관리를 위해 땅을 1×1 크기의 칸으로 나누어 놓았다. 각각의 칸은 (r, c)로 나타내며, r은 가장 위에서부터

www.acmicpc.net

1. 풀이방법

- 단순한 구현 문제입니다.

 

- 문제는 간단하고 이해도 어렵지 않지만, 시간제한이 0.3초 인 점을 감안하여야 합니다.

 

- 문제에서의 단계대로 차례차례 진행해줍니다.

 

 

2. 주의사항

- 전 처음에 시간제한 및 어린나이부터 진행되어야 한다는 문제를 보고 우선순위 큐를 생각해서 접근하였는데,

 

- 정답은 잘 뽑아내는 것 같으나, 시간초과가 계속 되어 결국 자료형을 vector로 바꿔서 봄에만 정렬을 하여 사용하였습니다.

 

- vector를 사용하자니, 죽은 나무를 뽑아내는 것이 문제였는데, vector는 index로 쉽게 접근이 가능하나 원하는 위치의데이터를 맘대로 뽑기는 어렵습니다.

 

- 그래서 양분이 부족해지는 지점이 딱 왔을 때, 그 이차원벡터배열의 맨뒤부터 양분/2를 더해주면서 pop_back() 해주었습니다.

 

 

3. 나의코드

#include<bits/stdc++.h>
using namespace std;

int n, m, K;
int ground[11][11]; // 양분의 양
vector<int> treeageset[11][11]; //나이 기준 정렬
int s2d2[11][11];
int dx[8] = { -1,-1,-1,0,0,1,1,1 };
int dy[8] = { -1,0,1,-1,1,-1,0,1 };
int tmpv[1001];
int presize[11][11]; 

void inputs() {
	cin >> n >> m >> K;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			ground[i][j] = 5;
			cin >> s2d2[i][j];
		}
	}
	int x, y, z;
	for (int i = 0; i < m; i++) {
		cin >> x >> y >> z;
		treeageset[x][y].push_back(z);
	}
}
bool boundcheck(int x, int y) {
	return (x >= 1 && x <= n && y >= 1 && y <= n);
}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	inputs();
	for (int i = 0; i < K; i++) { //1년

		//봄
		for (int j = 1; j <= n; j++) {
			for (int k = 1; k <= n; k++) {
				if (treeageset[j][k].empty()) continue;
				int tmpground = ground[j][k];
				ground[j][k] = 0;
				sort(treeageset[j][k].begin(), treeageset[j][k].end());
				int vsize = treeageset[j][k].size();
				for (int a = 0; a < vsize; a++) {
					if (tmpground >= treeageset[j][k][a]) {
						tmpground -= treeageset[j][k][a];
						treeageset[j][k][a]++;
					}
					else {
						for (int b = vsize - 1; b >= a; b--) {
							ground[j][k] += treeageset[j][k][b] / 2;
							treeageset[j][k].pop_back();
						}
						break;
					}
				}
				ground[j][k] += tmpground; //남은 양분+죽은나무의 양분
			}
		}


	//새로 추가되는 나무들은 번식시키지 않기 위해서
	for (int j = 1; j <= n; j++) { 
		for (int k = 1; k <= n; k++) {
			presize[j][k] = treeageset[j][k].size();
		}
	}
	//가을 번식
	for (int j = 1; j <= n; j++) {
		for (int k = 1; k <= n; k++) {
			for (int a = 0; a < presize[j][k]; a++) {
				if (treeageset[j][k][a] % 5 == 0) {
					for (int b = 0; b < 8; b++) {
						int nextx = j + dx[b];
						int nexty = k + dy[b];
						if (boundcheck(nextx, nexty)) {
							treeageset[nextx][nexty].push_back(1);
						}
					}
				}
			}
			ground[j][k] += s2d2[j][k]; //양분 보급
		}
	}
}
	int resultsum = 0;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			resultsum += treeageset[i][j].size();
		}
	}
	cout << resultsum;
	return 0;
}

 

'알고리즘 문제풀이 > 구현' 카테고리의 다른 글

백준 17825 [C++]  (0) 2021.03.07
백준 17837 [C++]  (0) 2021.03.06
백준 17779 [C++]  (0) 2021.03.05
백준 19237 [C++]  (0) 2021.03.05
백준 17140 [C++]  (0) 2021.01.24

www.acmicpc.net/problem/2726

 

2726번: 삼각 N-Queen

각 테스트 케이스에 대해서, 첫 줄에 놓을 수 있는 퀸의 최대 개수를 출력한다. 둘째 줄부터 N개의 줄에는 퀸의 위치를 출력한다. 제일 윗 줄의 번호는 1이고, 그 줄의 가장 왼쪽 칸의 번호는 1이

www.acmicpc.net

1. 풀이방법

 

- 처음에는 백트래킹을 이용한 모든 경우의수를 탐색하는 코드로 짰으나, 시간이 너무 오래걸립니다.

 

- 문제를 보면 N은 최대 1000이나 되기 때문에 다른방법을 찾아야 했고,

 

- 어쩔수 없이 직접 그려보며 규칙을 찾아야 했습니다......후... 근데 규칙 찾기도 상당히 난해합니다.

 

- 테스트케이스를 그리다 보면 어느정도 규칙이 보이는데, 문제는 시작점입니다.

 

- 시작점을 특정하는 것이 매우 어려웠습니다.

 

- 그림을 쭉 테스트케이스처럼 그려보다보면  (여기서 N=3 일 때는 테스트 케이스는 (1,1),(3,2)라고 했지만,

 

- 이것을 (2,1),(3,3)으로 바꿔서 생각하면 테스트케이스에서 어느정도의 일관성을 가진 규칙이 보입니다.

 

- 문제는 시작점을 특정하는 것인데 그려놓고 계속 보다보면 먼저 퀸의 개수가 측정이 가능한데

 

- (1,1,2,3,3,4,5,5,6,7,7,8,9,9,10,11,11,12......) 이런식입니다.

 

- 그래서 퀸의 개수를 먼저 배열에 싹다 구해서 넣어놓습니다.

 

- 그리고 시작점 (X,1)을 찾아야 하는데 이건 제가 찾은 규칙은 (N-퀸의개수+1)이였습니다

 

- 나머지는 부분은 테스트케이스를 직접 그려놓은 것을 바탕으로 구현하시면 됩니다.

 

 

 

 

2. 주의사항

 

- 특이하게도, 백트래킹으로 짠 시간초과가 나는 코드를 이용해서 규칙을 찾는데에 도움을 받아 풀었습니다.

(약 10~11정도까지는 조금 기다리면 나옵니다.) --> 이 코드로 1~11을  써가며 규칙을 찾아 풀었습니다.

 

 

3.나의코드

 

#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
#include<queue>
using namespace std;

int t;
int n;
int qarr[1005];

void initqueen() {
	int tmpq = 1;
	int index = 1;
	while (1) {
		if (index > 1000) break;
		qarr[index + 0] = tmpq;
		qarr[index + 1] = tmpq;
		qarr[index + 2] = tmpq + 1;
		tmpq += 2;
		index += 3;
	}
}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	initqueen();
	cin >> t;
	while (t--) {
		cin >> n;
		int startx = n - qarr[n] + 1;
		int starty = 1;
		int tmpx = 1;
		cout << qarr[n] << "\n";
		int tsize = qarr[n];
		while (tsize--) {
			cout << startx << " " << starty << "\n";
			if (startx == starty) {
				tmpx++;
				startx += 1;
				starty = tmpx;
				continue;
			}
			startx += 1; starty += 2;
		}
	}
	return 0;
}

'알고리즘 문제풀이 > 구현' 카테고리의 다른 글

백준 19237 [C++]  (0) 2021.03.05
백준 17140 [C++]  (0) 2021.01.24
백준 10993 [C++]  (0) 2021.01.16
백준 20061 [C++]  (0) 2020.12.28
백준 20056 [C++]  (0) 2020.12.23

www.acmicpc.net/problem/1051

 

1051번: 숫자 정사각형

N*M크기의 직사각형이 있다. 각 칸은 한 자리 숫자가 적혀 있다. 이 직사각형에서 꼭짓점에 쓰여 있는 수가 모두 같은 가장 큰 정사각형을 찾는 프로그램을 작성하시오. 이때, 정사각형은 행 또는

www.acmicpc.net

1. 풀이방법.

 

- 모든 정사각형의 4개의 꼭지점이 같은지 확인해주시면 됩니다.

 

- 입력이 붙어있길래 전 char 배열을 선언해서 입력을 받았습니다.

 

- 숫자가 들어오지만 , 계산하는 과정은 없고 같은지만 확인하면 되므로 따로 숫자로 변환시키지는 않았습니다.

 

 

 

 

2. 주의사항

 

- 하나짜리도 정사각형 입니다. (어찌보면 당연)

 

- 전그냥 따로 예외로 빼주었습니다. 

 

 

 

3. 나의코드

#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
using namespace std;

int N, M;
char nemo[51][51]; //0~ n-1, 0 ~ m-1

int maxcnt = 0;

void inputs() {
	cin >> N >> M;
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < M; j++) {
			cin >> nemo[i][j];
		}
	}
}
int samenemo(int x, int y, int c) {
	if (nemo[x][y] == nemo[x + c][y] && nemo[x][y] == nemo[x][y + c]
		&& nemo[x][y] == nemo[x + c][y + c]) return true;
	else return false;
}
void makecase(int cnt)
{
	for (int i = 0; i < N-cnt; i++) {
		for (int j = 0; j < M-cnt; j++) {
			if (samenemo(i, j,cnt)) {
				if (maxcnt < cnt) {
					maxcnt = cnt;
				}
			}
		}
	}
}
int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	inputs();
	if (N == 1 || M == 1) { cout << 1 << "\n"; return 0; }
	for (int i = 1; i < min(N, M); i++) {
		makecase(i); // 시작 index와 한 변의 길이
	}
	cout << (maxcnt+1)*(maxcnt+1) << "\n";

	return 0;
}

 

www.acmicpc.net/problem/9663

 

9663번: N-Queen

N-Queen 문제는 크기가 N × N인 체스판 위에 퀸 N개를 서로 공격할 수 없게 놓는 문제이다. N이 주어졌을 때, 퀸을 놓는 방법의 수를 구하는 프로그램을 작성하시오.

www.acmicpc.net

1. 풀이방법

 

- N개의 퀸을 놓을 수 있는 경우의 수 를 구하는 문제이고, 모든 경우의 수를 탐색하는데 시간을 신경써야합니다.

 

- 처음에는 그냥 dx[8],dy[8] 을 선언해서 8방향을 모두 탐색하다가 이미 다른 퀸이 있으면 리턴하고 라는 식으로

 

- 구현을 했다가.....N=5일때 까지 였나...? 까지 밖에 나오지 않았습니다...

 

- 처음에 N이 최대 14이길래 시간초과는 신경 안써도 되는 줄 알고 짰다가 당황한 문제였습니다.

 

- 체스판의 특성을 이용하여 x,y좌표의 특징들을 이용해서 놓을 수 있는지를 판단해야 했습니다.

 

 

 

 

 

2. 주의사항

 

- 체스판의 특성을 활용, 시간초과를 주의해야 함.

 

- 2차원 배열이 아닌 1차원배열을 이용하여 [x]=y를 통해 x,y 좌표를 나타내는 것이 처음에는 생소할 수 있음

 

 

 

 

3. 나의코드

#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;

int N;
int resultcount = 0;
int queenarr[15]; //[x]= y
 // 0~ N-1까지 사용
bool checking(int x, int y) {
	for (int i = 0; i < x; i++) {
		if ( abs(y-queenarr[i]) == abs(x -i) || queenarr[i] == y) {
			return false;
		}
	}
	return true;
}
void makecase(int x) {
	if (x == N) {
		resultcount++; return;
	}
	for (int i = 0; i < N; i++) {
		if (checking(x, i)) {
			queenarr[x] = i;
			makecase(x + 1);
		}
	}
}
int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	cin >> N;
	makecase(0);
	cout << resultcount << "\n";
	return 0;
}

'알고리즘 문제풀이 > 완탐' 카테고리의 다른 글

백준 2422 [C++] - 시간초과  (0) 2021.01.15
백준 18511 [C++]  (0) 2021.01.15
백준 1107 [C++]  (0) 2020.12.14
백준 14500 [C++]  (0) 2020.12.05
백준 17135 [C++]  (0) 2020.10.21

www.acmicpc.net/problem/7569

 

7569번: 토마토

첫 줄에는 상자의 크기를 나타내는 두 정수 M,N과 쌓아올려지는 상자의 수를 나타내는 H가 주어진다. M은 상자의 가로 칸의 수, N은 상자의 세로 칸의 수를 나타낸다. 단, 2 ≤ M ≤ 100, 2 ≤ N ≤ 100,

www.acmicpc.net

1. 풀이방법.

 

- 3차원배열을 이용한 bfs로 해결하였습니다.

 

- 처음에 input을 받을 때 전체토마토 수, 익은토마토 수를 체크한 후

 

- bfs를 돌면서 익을 때 마다 익은토마토수를 ++ 해주며,

 

- 큐가 비었을 때(종료조건) -> 익은토마토수 == 전체토마토수 이면 걸린시간을 출력

 

                                   -> 익은토마토수 != 전체토마토수 이면 (모두익힐 수 없음 -1출력)

 

 

 

 

 

2. 주의사항

 

- 3차원배열이므로 행,렬,높이 를 스스로 잘 설정하여 H,N,M 과 비교연산 등을 할 때 헷갈리지 않게 주의.

 

 

 

 

 

3. 나의코드

#include<iostream>
#include<algorithm>
#include<string>
#include<queue>
#include<vector>
using namespace std;

int tomatobox[101][101][101];//높이,세로행,가로행
bool visit[101][101][101];
int N, M, H;
int totaltomato;
int dx[6] = { 1,-1,0,0,0,0 }; //6방향탐색
int dy[6] = { 0,0,1,-1,0,0 };
int dz[6] = { 0,0,0,0,1,-1 };
struct tomato {
	int h, n, m;
};
queue<tomato> tmpq;
int timecount;
int tomatocount;

void inputs() {
	cin >> M >> N >> H;
	for (int i = 0; i < H; i++) {
		for (int j = 0; j < N; j++) {
			for (int k = 0; k < M; k++) {
				cin >> tomatobox[i][j][k];
				if (tomatobox[i][j][k] == 1) { //익은토마토
					totaltomato++;
					tomatocount++;
					tomatobox[i][j][k] = true;
					tmpq.push({ i,j,k });
				}
				if (tomatobox[i][j][k] == 0) { //익지않은 토마토
					totaltomato++;
				}
			}
		}
	}
}
bool sidecheck(int x, int y, int z) { //경계선 체크
	if (x >= 0 && x < H &&y >= 0 && y < N &&z >= 0 && z < M) return true;
	else return false;
}
void bfs() {
	while (1) {
		int qsize = tmpq.size();
		while (qsize--) {
			tomato thistomato = tmpq.front();
			tmpq.pop();
			for (int i = 0; i < 6; i++) {
				if (sidecheck(thistomato.h+dx[i], thistomato.n+dy[i], thistomato.m+dz[i])
					&&tomatobox[thistomato.h + dx[i]][thistomato.n + dy[i]][thistomato.m + dz[i]]==0 && visit[thistomato.h + dx[i]][thistomato.n + dy[i]][thistomato.m + dz[i]] == false) {
					visit[thistomato.h + dx[i]][thistomato.n + dy[i]][thistomato.m + dz[i]] = true;
					tomatocount++; //토마토가 익음
					tmpq.push({ thistomato.h + dx[i],thistomato.n + dy[i],thistomato.m + dz[i] });
				}
			}
		}
		if (tmpq.empty()) { //종료조건
			if (totaltomato == tomatocount) {
				cout << timecount << "\n";
				return;
			}
			else {
				cout << -1 << "\n";
				return;
			}
		}
		timecount++;
	}
}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	inputs();
	bfs();

	return 0;
}

'알고리즘 문제풀이 > DFS와 BFS' 카테고리의 다른 글

백준 16236 [C++]  (0) 2020.12.29
백준 2644 [C++]  (0) 2020.12.22
백준 1697 [C++]  (0) 2020.12.20
백준 16397 [C++]  (0) 2020.12.18
백준 6593 [C++]  (0) 2020.12.15

1. 배열

 

 

- 연속된 메모리 상에 위치 (배정) 된다.

 

- "시작주소 + (자료형의 크기) * INDEX " 를 통해서 접근이 가능하므로 배열의 이름과 INDEX만으로 쉽게 접근

    이 가능하다. (매우 큰 장점)

 

- 크기와 자료형을 지정해주어야 한다.

 

- 동적배열로 어느정도 해결이 가능하지만, 배열이 최대크기를 넘어설 때는 Array Doubling이 발생하는데 

 

- 두배 크기의 배열이 선언되고, 기존의 데이터들을 새로운 두배크기의 배열로 모두 옮겨야 하므로 O(n) 시간이 소요. 

 

-(여담으로 수업을 들을 당시에 그럼 n크기의 배열에서 계속 삽입,삭제,삽입,삭제가 일어나면 계속 새로운배열이 생기고

  시간이 오래걸리는 것 인가? 라는 질문이 있었는데, 데이터의 개수가 n+1이 되어서 2n짜리 배열을 선언해서 옮겼을 

  때, 삭제연산이 일어나서 다시 n이 되었을 때 바로 다시 크기가 n인 배열로 옮기진 않는다고 한다. 보통은 n/2 정도가 

  되었을 때 옮긴다고 한다.)

 

- 탐색, 삽입, 삭제

 

   (1) 탐색

     -> 원하는 위치가 존재할 경우 index로 바로 접근이 가능하다 (O(n))

     -> 특정한 value를 찾고 싶을 때는 앞쪽부터 탐색하므로 O(n)

 

    (2) 삽입

      -> 특정위치에 삽입한다면 그 위치부터 끝쪽 까지 위치하던 데이터 들을 모두 한칸씩 미뤄야 하므로 (O(n))

      -> 맨 뒤에 삽입일 경우 옮길 것이 없으므로 빠르지만, 최악의 경우는 맨 앞쪽에 삽입할 경우 이므로 n-1개를

          옮겨야 할 수도 있다.

 

    (3) 삭제

       -> 삭제된 위치로 부터 뒤에 있는 데이터들을 모두 앞쪽으로 한칸씩 당겨주어야한다. (삽입과 같은 맥락)

 

 

- 배열은 메모리상에 연속되게 위치하기 때문에 크기가 큰 배열을 선언하려고 할 경우 남은 공간의 합은 충분하더라도

 

- 연속된 공간이 확보되지 않을 경우 메모리 할당을 못 받을수도 있다.

 

 

2. 연결리스트( 링크드 리스트)

 

- 단순 연결 리스트 (simple linked list)와 이중 링크드 리스트(doubly linked list)가 존재

 

- (단순 연결 리스트)  - HEAD Pointer를 통해서 접근

 

- (이중 연결 리스트)  - HEAD,TAIL을 통해서 접근

 

- 위의 그림과 같이 연결리스트는 연속된 메모리 공간에서 존재하지 않고 다음 테이터를 가리키는 포인터를

   

- 통해서 다음 원소에 접근한다.

 

- 연속된 공간이 필요하지 않고, 크기를 미리 지정해줄 필요도 없다.

 

- 반면, 다음원소를 가리키는 포인터에 대한 공간낭비 (오버헤드)가 발생한다.

 

- 심한경우를 예로 들자면 char형을 저장하려고 하는 경우 실제 데이터는 1byte인데

 

- 이중 연결리스트로 구현할 경우 prev와 next에 해당하는 포인터들이 각각 4byte씩 이므로 총 9 byte를 차지 하게 된다.

   (하나의 노드 당) -- 이는 배보다 배꼽이 더 큰 격이다.

 

- 탐색, 삽입, 삭제

 

  (1) 탐색

    - 포인터를 따라서 찾아가야 하므로 탐색시간이 오래 걸린다. (O(N)

 

  (2) 삽입

     - 간단하다. 탐색이 끝난 상태(탐색은 오래걸림)라면 넣고자 하는 위치의 이전 노드의 next 포인터가 해당데이터를            가리키도록 수정하 고, 해당 데이터의 next 포인터가 원래 이전노드가 가리키던 다음 노드를 가리키도록 설정만             해주면 된다.

        (싱글 링크드 리스트일 경우. 이중을 경우 prev,와 next에 해당되는 포인터 모두를 수정)

     - 단순 연결리스트의 경우 head를 통해서만 접근하므로 앞 쪽에 데이터(노드)를 추가하는 것은 빠르다.

     - 이중 연결리스트의 경우 tail을 통해서도 접근이 가능하므로 앞,뒤쪽에 데이터(노드)를 추가하는 것은 빠르다.

 

  (3) 삭제

     - 삭제 역시 삽입과 마찬가지로 간단하다.

     - 이전 의 노드의 next 포인터를 다음 노드를 가리키도록 수정해 주면 된다.

        (싱글 링크드 리스트일 경우. 이중을 경우 prev,와 next에 해당되는 포인터 모두를 수정)

 

 

 

3. 배열과 연결리스트의 간단정리.

 

- 배열을 사용할 경우 index를 통한 접근이 간편하며, 이는 큰 장점이다

   저장할 데이터 수가 어느정도 정해져있고, 데이터들을 중간에 삽입,삭제가 많지 않을 떄 좋다.

  연속된 메모리 공간을 요구한다.

 

- 연결리스트를 사용할 경우, 데이터의 개수에 제한이 없고 , 연속된 공간의 메모리를 필요로 하지 않는다.

  데이터의 삽입, 삭제가 빈번하고 상대적으로 어떤 위치의 데이터에 대한 탐색이 적을경우 좋다.

  포인터에 대한 오버헤드가 발생한다.

'학부생 공부 > 자료구조' 카테고리의 다른 글

트리 (Tree)  (0) 2020.10.14
그래프 (Graph)  (0) 2020.05.03
벡터(Vector)  (0) 2020.02.15
큐(queue)  (0) 2020.02.14
스택 (Stack)  (0) 2020.02.13

www.acmicpc.net/problem/6593

 

6593번: 상범 빌딩

당신은 상범 빌딩에 갇히고 말았다. 여기서 탈출하는 가장 빠른 길은 무엇일까? 상범 빌딩은 각 변의 길이가 1인 정육면체(단위 정육면체)로 이루어져있다. 각 정육면체는 금으로 이루어져 있어

www.acmicpc.net

1. 풀이방법

 

- 3차원배열을 이용해야할 뿐 기초적인 BFS 문제입니다

 

- 범위검사와 BFS, 그리고 E에 도달하지 못했는데 큐가 비어있다면 더이상 갈 곳이 없는 것이므로

 

- 종료조건을 출력하고 나가면 됩니다.

 

 

 

 

2. 주의사항

 

- 구현에 몰두해서 짜다보니 메모리 초과가 떴는데 왜 그런가 봤더니 방문체크를 큐에서 꺼낼 때 하고 있었습니다.

 

- 그럴경우, 여러정점에서 동시방문하고자 할 수 있기 때문에 문제가 발생할 수 있습니다.

 

- BFS를 구현할 때는 방문체크를 큐에 넣을 떄 해줍시다.

 

 

 

 

3.나의코드

#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
#include<queue>
using namespace std;

int L, R, C;
int seconds;
char sangbumbuilding[31][31][31];
bool visit[31][31][31];
int dx[6] = { 1,-1,0,0,0,0 }; //6방향 탐색
int dy[6] = { 0,0,1,-1,0,0 };
int dz[6] = { 0,0,0,0,1,-1 };
struct area {
	int x, y, z;
};

queue<area> tmpq;
area S;
area E;
area tmpa, tmparea;
bool inputs() {
	cin >> L >> R >> C;
	if (L == 0 && R == 0 && C == 0) return true;

	for (int i = 1; i <= L; i++) {
		for (int j = 1; j <= R; j++) {
			for (int k = 1; k <= C; k++) {
				visit[i][j][k] = false;
				cin >> sangbumbuilding[i][j][k];
				if(sangbumbuilding[i][j][k]=='S'){
					S.x = i; S.y = j; S.z = k;
				}
				if (sangbumbuilding[i][j][k] == 'E') {
					E.x = i; E.y = j; E.z = k;
				}
			}
		}
	}
	return false;
}

void bfs(area s) {
	tmpq.push(s);
	while (1) {
		if (tmpq.empty()) { cout << "Trapped!" << "\n"; return; }
		int tmpsize = tmpq.size();
		while(tmpsize--) { //1초당
			tmpa = tmpq.front();
			tmpq.pop();
			if (tmpa.x == E.x &&tmpa.y == E.y&&tmpa.z == E.z) {
				cout << "Escaped in "<<seconds<<" minute(s)."<<"\n"; return;
			}
			for (int i = 0; i < 6; i++) { //6방향탐색
				//범위 검사
				if (tmpa.x + dx[i] >= 1 && tmpa.x + dx[i] <= L && tmpa.y + dy[i] >= 1 && tmpa.y + dy[i] <= R && tmpa.z + dz[i] >= 1 && tmpa.z + dz[i] <= C) {
					if (sangbumbuilding[tmpa.x + dx[i]][tmpa.y + dy[i]][tmpa.z + dz[i]] == '.'|| sangbumbuilding[tmpa.x + dx[i]][tmpa.y + dy[i]][tmpa.z + dz[i]] == 'E') {
						if (visit[tmpa.x + dx[i]][tmpa.y + dy[i]][tmpa.z + dz[i]] == false) {
							tmparea.x = tmpa.x + dx[i]; tmparea.y = tmpa.y + dy[i]; tmparea.z = tmpa.z + dz[i];
							visit[tmparea.x][tmparea.y][tmparea.z] = true;
							tmpq.push(tmparea);
						}
					}
				}
			}
		}
		seconds++;
	}
}
void resetqueue() {
	while (1) {
		if (tmpq.empty()) return;
		tmpq.pop();
	}
}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	while (1) {
		resetqueue();
		if(inputs()) break;
		seconds = 0;
		bfs(S);
	}
	return 0;
}

'알고리즘 문제풀이 > DFS와 BFS' 카테고리의 다른 글

백준 1697 [C++]  (0) 2020.12.20
백준 16397 [C++]  (0) 2020.12.18
백준 15684 [C++]  (0) 2020.12.09
백준 15683 [C++]  (0) 2020.12.08
백준 11404 [C++] ,플로이드 워셜  (0) 2020.10.26

+ Recent posts