www.acmicpc.net/problem/16236

 

16236번: 아기 상어

N×N 크기의 공간에 물고기 M마리와 아기 상어 1마리가 있다. 공간은 1×1 크기의 정사각형 칸으로 나누어져 있다. 한 칸에는 물고기가 최대 1마리 존재한다. 아기 상어와 물고기는 모두 크기를 가

www.acmicpc.net

 

1. 풀이방법

 

- BFS 문제. DFS로도 풀어보았지만 로직은 맞는 것 같지만 역시나 시간 초과가 나옵니다. (코드는 첨부)

 

- 상어의 위치로 부터 조건에 가장 부합하는 물고기 위치를 BFS로 탐색해 찾아낸 다음

 

- 그 위치의 물고기를 먹고 상어의크기를 조정이 필요할 경우 해주고 그 위치로 아기상어를 옮겨 주시면 됩니다.

 

- 저는 DFS를 먼저 풀고 거기서 재활용할 함수들은 재활용하고 makefishcase만 bfs로 바꿔서 구현하여서,

 

- 불필요한 부분도 들어있습니다. 깔끔하지 않습니다.

 

 

 

2. 주의사항

 

- 한가지 있는데, 저와 같은 케이스인 분들을 위해 기록합니다.

 

- bfs로 짰는데 "시간초과" 라는 결과를 얻었습니다.

 

- 코드를 아무리 봐도 시간초과가 나올만한 연산을 하는 곳이 없습니다.

 

- 이럴경우 거의 십중팔구 무한루프에 빠지는 테스트케이스가 존재한다는 뜻입니다.

 

- 그것을 곰곰히 생각해보니, 

 

- 이러한 경우 입니다

 

  9 0 0

  4 4 4

  0 0 1

 

-저의 코드에서는 전체 바다에서 먹을 수 있는 물고기가 존재하는지 체크하는 함수가 있는데,

 

- 그 함수는 이러한 케이스에서 1이라는 물고기가 있으므로 break;를 걸지 않아서 무한루프에 빠져

 

- 시간초과가 나오는 것이였습니다.

 

- 물론 종료조건 함수를 훨씬 정교하고 예쁘게 만드셨다면 해당되지 않으실 수 도 있습니다!

 

3. 나의코드

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

int dx[4] = { 1,-1,0,0 }; //상하좌우 4방향 탐색
int dy[4] = { 0,0,-1,1 };
int sea[21][21];
bool visit[21][21];
int N;
int resultsecond;
int tmpeat = 0;
int sharksize = 2;
int sharkx, sharky;
int failsecond = -1;

struct fish {
	int x, y, far;
};
vector<fish> farr;
void inputs() {
	cin >> N;
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++) {
			cin >> sea[i][j];
			if (sea[i][j] == 9) { sharkx = i; sharky = j; }
		}
	}
}
bool checksea() {
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++) {
			if (sea[i][j] > 0 && sea[i][j] < sharksize && sea[i][j] != 9) { return false; }
		}
	}
	return true; //더이상 잡아 먹을 것 이 없음
}
void visitclear() {
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++) {
			visit[i][j] = false;
		}
	}
}
queue<fish> tmpq;
void makefishcase(int x, int y) {
	tmpq.push({ x,y,0 });
	int cnt = 0;
	while (1) {
		int si = tmpq.size();
		if (si == 0) { failsecond = resultsecond; break; }
		while (si--) {
			int tx = tmpq.front().x;
			int ty = tmpq.front().y;
			tmpq.pop();
			if (sea[tx][ty] > 0 && sea[tx][ty] < sharksize && sea[tx][ty] != 9) {
				farr.push_back({ tx,ty,cnt });
			}
			for (int i = 0; i < 4; i++) {
				int nextx = tx + dx[i]; int nexty = ty + dy[i];
				if (nextx >= 0 && nextx < N && nexty >= 0 && nexty < N) {
					if (visit[nextx][nexty] == false && sea[nextx][nexty] <= sharksize) {
						visit[nextx][nexty] = true; 
						tmpq.push({ nextx,nexty,0 }); 
					}
				}
			}
		}
		if (farr.empty() == false) break;
		cnt++;
	}
}
bool compare(fish& lh, fish& rh) {
	if (lh.far < rh.far) return true;
	else if (lh.far == rh.far) {
		if (lh.x < rh.x) return true;
		else if (lh.x == rh.x) {
			if (lh.y < rh.y) return true;
			else return false;
		}
		else return false;
	}
	else return false;
}
void queuereset() {
	while (!tmpq.empty()) {
		tmpq.pop();
	}
}
void eatfish() {
	queuereset();
	makefishcase(sharkx, sharky);
	if (failsecond != -1) return;
	sort(farr.begin(), farr.end(), compare); //거리 순 > 위에있는순> 왼쪽에 있는순으로 소팅
	sea[sharkx][sharky] = 0;
	sharkx = farr[0].x; sharky = farr[0].y;
	tmpeat++;
	if (sharksize == tmpeat) {
		tmpeat = 0; sharksize++;
	}
	sea[sharkx][sharky] = 9;
	resultsecond += farr[0].far;
	visitclear();
	farr.clear();
}
int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	inputs();
	while (1) {
		if (checksea()) break;
		visit[sharkx][sharky] = true;
		eatfish();
		if (failsecond != -1) break;
	}
	if (failsecond == -1) {
		cout << resultsecond << "\n";
	}
	else { cout << failsecond << "\n"; }
	return 0;
}

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

백준 19238 [C++]  (0) 2021.01.17
백준 17142 [C++]  (0) 2021.01.17
백준 2644 [C++]  (0) 2020.12.22
백준 7569 [C++]  (1) 2020.12.20
백준 1697 [C++]  (0) 2020.12.20

www.acmicpc.net/problem/2644

 

2644번: 촌수계산

사람들은 1, 2, 3, …, n (1≤n≤100)의 연속된 번호로 각각 표시된다. 입력 파일의 첫째 줄에는 전체 사람의 수 n이 주어지고, 둘째 줄에는 촌수를 계산해야 하는 서로 다른 두 사람의 번호가 주어진

www.acmicpc.net

1. 풀이방법

 

- 촌수를 계산하는 문제입니다 (두 정점 사이에)

 

- dfs를 통해서 계산을 하였고 간선의 가중치 (촌수가 1씩 증가)가 1이므로 bfs로도 쉽게 표현 가능할 것으로 보입니다.

 

- 두 정점이 인접했는지를 확인하는 연산이 주로 쓰이므로 인접행렬방식으로 그래프를 구현하였습니다.

 

 

 

2. 주의사항

 

- 딱히없음, 특별한 조건도 없고..

 

 

3. 나의코드

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

int n, m;
int target1, target2;
bool connected[101][101];
bool visited[101];
bool suc;

void inputs() {
	cin >> n >> target1 >> target2;
	cin >> m;
	int tmp1, tmp2;
	for (int i = 0; i < m; i++) {
		cin >> tmp1 >> tmp2;
		connected[tmp1][tmp2] = true;
		connected[tmp2][tmp1] = true;
	}
}

void findchon(int t,int cnt) {
	visited[t] = true;
	if (t == target2) { cout << cnt << "\n";
	suc = true; return;
	}
	for (int i = 1; i <= n; i++) {
		if (i != t) {
			if (connected[t][i] && !visited[i]) {
				findchon(i, cnt + 1);
			}
			if (suc) break;
		}
	}
}


int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	inputs();
	findchon(target1,0);
	if (suc == false) cout << -1 << "\n";

	return 0;
}

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

백준 17142 [C++]  (0) 2021.01.17
백준 16236 [C++]  (0) 2020.12.29
백준 7569 [C++]  (1) 2020.12.20
백준 1697 [C++]  (0) 2020.12.20
백준 16397 [C++]  (0) 2020.12.18

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

www.acmicpc.net/problem/1697

 

1697번: 숨바꼭질

수빈이는 동생과 숨바꼭질을 하고 있다. 수빈이는 현재 점 N(0 ≤ N ≤ 100,000)에 있고, 동생은 점 K(0 ≤ K ≤ 100,000)에 있다. 수빈이는 걷거나 순간이동을 할 수 있다. 만약, 수빈이의 위치가 X일

www.acmicpc.net

1. 풀이방법.

 

- 0<N==K<100000 이 되는 모든 경우의 수를 탐색해야합니다.

 

- 움직일 수 있는 경우의 수는 3가지 X+1,X-1,2*N

 

- DFS로 모든 경우의수를 탐색할경우 +1,-1씩 이동하는경우 때문에 스택오버플로우가 발생할 것 이라 판단했습니다.

 

- 그래서 큐를 이용하여 BFS로 해결하였습니다. 

 

- 딱히 다른 조건도 없어 기본적인 문제였습니다.

 

 

 

 

2. 주의사항

 

- 문제 조건 해석 및 판단.

 

 

 

 

3.나의코드

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

int N, K;
int resultsecond;
bool visit[100001]; //방문체크
queue<int> tmpq;


void bfs() {
	while (1) {
		int qsize = tmpq.size();
		while (qsize--) {
			int thisvalue = tmpq.front();
			tmpq.pop();

			if (thisvalue == K) { //종료조건
				cout << resultsecond << "\n";  return;
			}

			if (thisvalue - 1 >= 0 && visit[thisvalue-1] == false) {
				visit[thisvalue - 1] = true;
				tmpq.push(thisvalue - 1);
			}
			if (thisvalue + 1 <= 100000 && visit[thisvalue+1] == false) {
				visit[thisvalue + 1] = true;
				tmpq.push(thisvalue + 1);
			}
			if (2 * thisvalue <= 100000 && visit[2*thisvalue] == false) {
				visit[2 * thisvalue] = true;
				tmpq.push(2 * thisvalue);
			}
		}
		resultsecond++;
	}
}



int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	cin >> N >> K;
	tmpq.push(N);
	visit[N] = true;
	bfs();

	return 0;
}

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

백준 2644 [C++]  (0) 2020.12.22
백준 7569 [C++]  (1) 2020.12.20
백준 16397 [C++]  (0) 2020.12.18
백준 6593 [C++]  (0) 2020.12.15
백준 15684 [C++]  (0) 2020.12.09

www.acmicpc.net/problem/16397

 

16397번: 탈출

첫 번째 줄에 N (0 ≤ N ≤ 99,999), T (1 ≤ T ≤ 99,999), G (0 ≤ G ≤ 99,999)가 공백 하나를 사이에 두고 주어진다. 각각 N은 LED로 표현된 수, T는 버튼을 누를 수 있는 최대 횟수, G는 탈출을 위해 똑같이

www.acmicpc.net

1. 풀이방법

 

- 처음에는 재귀를 이용한 DFS로 모든 경우를 탐색하려고 생각하고 코드를 구상했으나,

 

- 문제 조건을 보시면 T가 최대 99,999이고, A버튼만 누를 경우 숫자가 1씩 증가하는데 N이 0일경우를 생각해보면

 

- 재귀를 이용해서 짰을때 stackoverflow를 만났습니다. (조건을 보고 미리 생각했어야되는데....으휴 덤벙덤벙)

 

- 원리는 비슷한데 queue를 이용해서 bfs로 똑같이 옮겨서 해결했습니다.

 

 

 

2. 주의사항

 

- 조건도 꼼꼼히 파악하자.

 

 

3. 나의코드

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

int N, T, G;
bool visit[100000];
queue<pair<int,int>> tmpq;



int getmodnum(int tmp) {
	int maxmod = 1;
	while (1) {
		if (tmp == 0) break;
		tmp /= 10;
		maxmod *= 10;
	}
	maxmod /= 10;
	return maxmod;
}

int bfs() {
	while (!tmpq.empty()) {
		int tmpn = tmpq.front().first;
		int tmpcnt = tmpq.front().second;
		tmpq.pop();
		if (tmpcnt > T) break;
		if (tmpn == G) return tmpcnt;

		int num = tmpn + 1;
		if (num < 100000 && visit[num] == false) {
			visit[num] = true;
			tmpq.push({ num,tmpcnt + 1 });
		}

		num = tmpn * 2;
		if (num < 100000) {
			int minusnum = getmodnum(num);
			num -= minusnum;
			if (num < 100000 && visit[num] == false) {
				visit[num] = true;
				tmpq.push({ num,tmpcnt + 1 });
			}
		}
	}
	return -1;
}

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

	cin >> N >> T >> G;
	tmpq.push({N, 0}); //시작점
	visit[N] = true;
	int result = bfs();
	if (result == -1) cout << "ANG" << "\n";
	else cout << result << "\n";
	return 0;
}

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

백준 7569 [C++]  (1) 2020.12.20
백준 1697 [C++]  (0) 2020.12.20
백준 6593 [C++]  (0) 2020.12.15
백준 15684 [C++]  (0) 2020.12.09
백준 15683 [C++]  (0) 2020.12.08

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

www.acmicpc.net/problem/15684

 

15684번: 사다리 조작

사다리 게임은 N개의 세로선과 M개의 가로선으로 이루어져 있다. 인접한 세로선 사이에는 가로선을 놓을 수 있는데, 각각의 세로선마다 가로선을 놓을 수 있는 위치의 개수는 H이고, 모든 세로선

www.acmicpc.net

1. 풀이방법

 

- 일단 사다리에 대한 표현을 어떻게 할까 고민하다가 저는 char 2차원배열을 선언해서 'R' 또는 'L' 을 넣어서

 

- 오른쪽으로 가는 경우, 왼쪽으로 가는 경우를 구현했습니다.

 

- 그렇게 선언한 후 어떤식으로 찾을 까 고민을 하다가(약간 막막)

 

- 추가하는 최대 line의 수가 3보다 많아지면 그냥 -1을 출력하라는 조건을 보고 아 dfs를 돌리는데 깊이가 3보다 커지

 

- 면 return을 하는 식으로 구현해야겠다 ( 깊이 3정도니까 전체를 다 보아도 시간초과가 안나겠지???) 라는 생각...!!

 

 

 

 

2. 주의사항

 

- 저 같은 경우 아주 초보적인 실수를 했는데 코드에도 주석으로 달아 놓겠지만.....

 

- 2차원배열로 dfs를 돌때!!

 

- for(int i=x;i<....){

        for(int j=y;j<....{

                     function (i,j+1,cnt+1);       

                  }

            }

 

-이런식으로 했다가 헤맸습니다... 이러면 안쪽반복문을 i가 갱신될때는 0부터 돌아야하는데 계속 y부터만 돌게 됩니다

 

- 저는 안쪽반복문은 그냥 계속 0부터 돌게끔 수정했습니다....(그래서인지 다른 사람들보다는 시간이 약간 길게 걸린 듯)

 

 

 

 

 

3. 나의코드

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

int N, M, H;
char sadari[31][11];
int a, b;
int minresult=4; //3 이하; 그 이상은 -1;
bool suc = false;

void inputs() {
	cin >> N >> M >> H;
	for (int i = 0; i < M; i++) {
		cin >> a >> b;
		sadari[a][b] = 'R';
		sadari[a][b + 1] = 'L';
	}
}
bool checkingright() {
	for (int i = 1; i <= N; i++) {
		int resultcount = i;
		for (int j = 1; j <= H; j++){
			if (sadari[j][i] == 'R') i++;
			else if(sadari[j][i]=='L') i--;
			else continue;
		}
		if (resultcount != i) return false;
		i = resultcount;
	}
	return true;
}
void findline(int x,int cnt) {
	if (cnt > 3) { return; } 
	if (checkingright() == true) {
		if (minresult > cnt) { minresult = cnt; }
		suc = true;
		return;
	}; //성공
	for (int a = x; a < N; a++) {
		for (int b = 1; b <= H; b++) {// for(int b=y;b<=H;b++) xxxxxxxxxx!
			if (sadari[b][a] != 0 || sadari[b][a+1]!=0) continue; //이미 연결되어있음
			else {
				sadari[b][a] = 'R';
				sadari[b][a + 1] = 'L';

				findline(a,cnt + 1);  //findline(a,b+1,cnt+1) xxxxxxxx!

				sadari[b][a + 1] = 0;
				sadari[b][a] = 0;
			}
		}
	}
}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	inputs();
	findline(1,0);
	if (suc == false) { cout << -1 << "\n"; }
	else cout << minresult << "\n";
	return 0;
}

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

백준 16397 [C++]  (0) 2020.12.18
백준 6593 [C++]  (0) 2020.12.15
백준 15683 [C++]  (0) 2020.12.08
백준 11404 [C++] ,플로이드 워셜  (0) 2020.10.26
백준 16234[C++]  (0) 2020.10.25

www.acmicpc.net/problem/15683

 

15683번: 감시

스타트링크의 사무실은 1×1크기의 정사각형으로 나누어져 있는 N×M 크기의 직사각형으로 나타낼 수 있다. 사무실에는 총 K개의 CCTV가 설치되어져 있는데, CCTV는 5가지 종류가 있다. 각 CCTV가 감

www.acmicpc.net

1. 풀이방법.

 

- 전 깊이우선탐색(DFS)로 구현하여 해결하였습니다.

 

- 깊이우선 탐색을 통해 결국 모든 경우의 수를 모두 확인하는 방식입니다.

 

- 먼저 카메라를 carr벡터에 입력받을 때 모두 저장해 놓은뒤

 

- 1번카메라 부터 보면서 1번카메라가 북쪽을 비출 때 -> (깊이 1증가)-> 2번카메라가 어딘가 비출떄.... ->

 

- 종료조건은 모든 카메라가 어딘가를 비추고 있을 때 입니다.

 

 

 

 

 

2. 주의사항 .

 

- 비춘후 다시 맵의 수정한 부분을 0으로 고쳐줬는데 그때 vector를 잘못사용해서 잠시 오류를 겪었습니다.

 

 

 

 

3. 나의코드.

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

int N, M;
int cctvmap[8][8];
struct cctv {
	int x; int y; int num;
};
vector<cctv> carr;
int dx[4] = { -1,0,1,0 }; //북동남서
int dy[4] = { 0,1,0,-1 };

void inputs() {
	cin >> N >> M;
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < M; j++) {
			cin >> cctvmap[i][j];
			if (cctvmap[i][j] == 6) continue;
			else if (cctvmap[i][j] == 0) continue;
			else { //1,2,3,4,5
				cctv tc; tc.x = i; tc.y = j; tc.num = cctvmap[i][j];
				carr.push_back(tc);
			}
		}
	}
}
int minresult = 64;

void countzero() {
	int resultzero = 0;
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < M; j++) {
			if (cctvmap[i][j] == 0) resultzero++;
		}
	}
	if (resultzero < minresult) minresult = resultzero;
}

void findzero(int countcctv) {
	if (countcctv == carr.size()) {
		countzero();
		 return;
	}
	for (int i = countcctv; i < carr.size(); i++) {
		if(carr[i].num==1){
			for (int j = 0; j < 4; j++) {
				vector<pair<int, int>> tmpvector;
				int tmpx = carr[i].x; int tmpy = carr[i].y;
				while (1) {
					if (tmpx < 0 || tmpx >= N || tmpy < 0 || tmpy >= M||cctvmap[tmpx][tmpy]==6) { break; } //범위를 넘거나 벽이거나
					if (cctvmap[tmpx][tmpy] == 0) {
						cctvmap[tmpx][tmpy] = 7;
						pair<int, int> tmpp; tmpp.first = tmpx; tmpp.second = tmpy;
						tmpvector.push_back(tmpp);
					}
					tmpx += dx[j]; tmpy += dy[j]; //그 방향으로 계속 전진
				}
				findzero(i + 1);
				for (int k = 0; k < tmpvector.size(); k++) { //다시 맵을 원상태로
					cctvmap[tmpvector[k].first][tmpvector[k].second] = 0;
				}
				tmpvector.clear();
			}
		}
		else if (carr[i].num == 2) {
			for (int j = 0; j < 2; j++) {
				vector<pair<int, int>> tmpvector;
				int tmpx = carr[i].x; int tmpy = carr[i].y;
				while (1) {
					if (tmpx < 0 || tmpx >= N || tmpy < 0 || tmpy >= M || cctvmap[tmpx][tmpy] == 6) { break; } //범위를 넘거나 벽이거나
					if (cctvmap[tmpx][tmpy] == 0) {
						cctvmap[tmpx][tmpy] = 7;
						pair<int, int> tmpp; tmpp.first = tmpx; tmpp.second = tmpy;
						tmpvector.push_back(tmpp);
					}
					tmpx += dx[j]; tmpy += dy[j]; //그 방향으로 계속 전진
				}
				tmpx = carr[i].x; tmpy = carr[i].y;
				while (1) {
					if (tmpx < 0 || tmpx >= N || tmpy < 0 || tmpy >= M || cctvmap[tmpx][tmpy] == 6) { break; } //범위를 넘거나 벽이거나
					if (cctvmap[tmpx][tmpy] == 0) {
						cctvmap[tmpx][tmpy] = 7;
						pair<int, int> tmpp; tmpp.first = tmpx; tmpp.second = tmpy;
						tmpvector.push_back(tmpp);
					}
					tmpx += dx[j+2]; tmpy += dy[j+2]; //그 방향으로 계속 전진
				}
				findzero(i + 1);
				for (int k = 0; k < tmpvector.size(); k++) { //다시 맵을 원상태로
					cctvmap[tmpvector[k].first][tmpvector[k].second] = 0;
				}
				tmpvector.clear();
				}
			}
		else if(carr[i].num==3){
			for (int j = 0; j < 4; j++) {
				vector<pair<int, int>> tmpvector;
				int tmpx = carr[i].x; int tmpy = carr[i].y;
				while (1) {
					if (tmpx < 0 || tmpx >= N || tmpy < 0 || tmpy >= M || cctvmap[tmpx][tmpy] == 6) { break; } //범위를 넘거나 벽이거나
					if (cctvmap[tmpx][tmpy] == 0) {
						cctvmap[tmpx][tmpy] = 7;
						pair<int, int> tmpp; tmpp.first = tmpx; tmpp.second = tmpy;
						tmpvector.push_back(tmpp);
					}
					tmpx += dx[j]; tmpy += dy[j]; //그 방향으로 계속 전진
				}
				tmpx = carr[i].x; tmpy = carr[i].y;
				while (1) {
					if (tmpx < 0 || tmpx >= N || tmpy < 0 || tmpy >= M || cctvmap[tmpx][tmpy] == 6) { break; } //범위를 넘거나 벽이거나
					if (cctvmap[tmpx][tmpy] == 0) {
						cctvmap[tmpx][tmpy] = 7;
						pair<int, int> tmpp; tmpp.first = tmpx; tmpp.second = tmpy;
						tmpvector.push_back(tmpp);
					}
					tmpx += dx[(j+1)%4]; tmpy += dy[(j+1)%4]; //그 방향으로 계속 전진

				}
				findzero(i+ 1);
				for (int k = 0; k < tmpvector.size(); k++) { //다시 맵을 원상태로
					cctvmap[tmpvector[k].first][tmpvector[k].second] = 0;
				}
				tmpvector.clear();
			}
		}
		else if(carr[i].num==4){
			for (int j = 0; j < 4; j++) {
				vector<pair<int, int>> tmpvector;
				int tmpx = carr[i].x; int tmpy = carr[i].y;
				while (1) {
					if (tmpx < 0 || tmpx >= N || tmpy < 0 || tmpy >= M || cctvmap[tmpx][tmpy] == 6) { break; } //범위를 넘거나 벽이거나
					if (cctvmap[tmpx][tmpy] == 0) {
						cctvmap[tmpx][tmpy] = 7;
						pair<int, int> tmpp; tmpp.first = tmpx; tmpp.second = tmpy;
						tmpvector.push_back(tmpp);
					}
					tmpx += dx[j]; tmpy += dy[j]; //그 방향으로 계속 전진

				}
				 tmpx = carr[i].x;tmpy = carr[i].y;
				while (1) {
					if (tmpx < 0 || tmpx >= N || tmpy < 0 || tmpy >= M || cctvmap[tmpx][tmpy] == 6) { break; } //범위를 넘거나 벽이거나
					if (cctvmap[tmpx][tmpy] == 0) {
						cctvmap[tmpx][tmpy] = 7;
						pair<int, int> tmpp; tmpp.first = tmpx; tmpp.second = tmpy;
						tmpvector.push_back(tmpp);
					}
					tmpx += dx[(j+1)%4]; tmpy += dy[(j+1)%4]; //그 방향으로 계속 전진

				}
				 tmpx = carr[i].x; tmpy = carr[i].y;
				while (1) {
					if (tmpx < 0 || tmpx >= N || tmpy < 0 || tmpy >= M || cctvmap[tmpx][tmpy] == 6) { break; } //범위를 넘거나 벽이거나
					if (cctvmap[tmpx][tmpy] == 0) {
						cctvmap[tmpx][tmpy] = 7;
						pair<int, int> tmpp; tmpp.first = tmpx; tmpp.second = tmpy;
						tmpvector.push_back(tmpp);
					}
					tmpx += dx[(j + 2) % 4]; tmpy += dy[(j + 2) % 4]; //그 방향으로 계속 전진

				}
				findzero(i + 1);
				for (int k = 0; k < tmpvector.size(); k++) { //다시 맵을 원상태로
					cctvmap[tmpvector[k].first][tmpvector[k].second] = 0;
				}
				tmpvector.clear();
			}
		}
		else { //5
		vector<pair<int, int>> tmpvector;
		int tmpx = carr[i].x; int tmpy = carr[i].y;
		while (1) {
			if (tmpx < 0 || tmpx >= N || tmpy < 0 || tmpy >= M || cctvmap[tmpx][tmpy] == 6) { break; } //범위를 넘거나 벽이거나
			if (cctvmap[tmpx][tmpy] == 0) {
				cctvmap[tmpx][tmpy] = 7;
				pair<int, int> tmpp; tmpp.first = tmpx; tmpp.second = tmpy;
				tmpvector.push_back(tmpp);
			}
			tmpx += dx[0]; tmpy += dy[0]; //그 방향으로 계속 전진

		}
		tmpx = carr[i].x; tmpy = carr[i].y;
		while (1) {
			if (tmpx < 0 || tmpx >= N || tmpy < 0 || tmpy >= M || cctvmap[tmpx][tmpy] == 6) { break; } //범위를 넘거나 벽이거나
			if (cctvmap[tmpx][tmpy] == 0) {
				cctvmap[tmpx][tmpy] = 7;
				pair<int, int> tmpp; tmpp.first = tmpx; tmpp.second = tmpy;
				tmpvector.push_back(tmpp);
			}
			tmpx += dx[1]; tmpy += dy[1]; //그 방향으로 계속 전진

		}
		tmpx = carr[i].x; tmpy = carr[i].y;
		while (1) {
			if (tmpx < 0 || tmpx >= N || tmpy < 0 || tmpy >= M || cctvmap[tmpx][tmpy] == 6) { break; } //범위를 넘거나 벽이거나
			if (cctvmap[tmpx][tmpy] == 0) {
				cctvmap[tmpx][tmpy] = 7;
				pair<int, int> tmpp; tmpp.first = tmpx; tmpp.second = tmpy;
				tmpvector.push_back(tmpp);
			}
			tmpx += dx[2]; tmpy += dy[2]; //그 방향으로 계속 전진

		}
		tmpx = carr[i].x;tmpy = carr[i].y;
		while (1) {
			if (tmpx < 0 || tmpx >= N || tmpy < 0 || tmpy >= M || cctvmap[tmpx][tmpy] == 6) { break; } //범위를 넘거나 벽이거나
			if (cctvmap[tmpx][tmpy] == 0) {
				cctvmap[tmpx][tmpy] = 7;
				pair<int, int> tmpp; tmpp.first = tmpx; tmpp.second = tmpy;
				tmpvector.push_back(tmpp);
			}
			tmpx += dx[3]; tmpy += dy[3]; //그 방향으로 계속 전진
		}
		findzero(i + 1);
		for (int k = 0; k < tmpvector.size(); k++) { //다시 맵을 원상태로
			cctvmap[tmpvector[k].first][tmpvector[k].second] = 0;
		}
		tmpvector.clear();
		}
	}
}
int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	inputs();
	findzero(0);
	cout << minresult << "\n";
	return 0;
}

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

백준 6593 [C++]  (0) 2020.12.15
백준 15684 [C++]  (0) 2020.12.09
백준 11404 [C++] ,플로이드 워셜  (0) 2020.10.26
백준 16234[C++]  (0) 2020.10.25
백준 18405 [C++]  (0) 2020.10.25

+ Recent posts