www.acmicpc.net/problem/20061

 

20061번: 모노미노도미노 2

모노미노도미노는 아래와 같이 생긴 보드에서 진행되는 게임이다. 보드는 빨간색 보드, 파란색 보드, 초록색 보드가 그림과 같이 붙어있는 형태이다. 게임에서 사용하는 좌표 (x, y)에서 x는 행,

www.acmicpc.net

1. 풀이방법

 

- 문제의 조건을 그대로 구현하는 문제입니다.

 

 

- 문제가 길긴 하지만 테스트케이스 와 문제자체(그림)이 친절하게 나와있어서 과정을 체크하기 편했습니다.

 

 

- 딱히 알고리즘을 사용할 건 없고 조건에 맞춘 구현만 해주시면 됩니다.

 

 

2. 주의사항

 

- 두번정도 틀린 후에 정답을 맞췄는데, 첫번째 오답의 경우 도미노를 밀 때 효율적으로 짠다셈 치고 뒤에서 부터

 

 

- 탐색을 하면서 도형의 자리를 찾았는데 , 오답이 뜬후 디버깅하며 지도 형태를 보니

 

 

- (이러한 경우)

 

 

- 0 0 0 1                    1 0 0 1

  0 1 0 1        (--->)   1 1 0 1  (정답)

 

 

 이렇게 되어야 하는데,

 

 

                                 0 0 1 1

                  (--->)     0 1 1 1 (오답)

 

 

- 이러한 실수를 했어서, 앞쪽부터 탐색하는 것으로 바꾸었습니다. (앞으로도 이런문제에서 주의하자..!!)

 

 

- 두번째 오답은 도형 유형이 3가지 있는데 테트리스를 생각해 보시면 이게 두줄이 한번에 clear 되는 경우가 발생할 수

 

 

- 있습니다. 저 같은 경우 코드 상에서 뒤쪽 부터 탐색 하며 한 행 또는 열 이 클리어 된다면 앞쪽에서 한칸씩 당겨오는

 

 

- 방식으로 구현했는데, 이렇게 구현할 경우 땡겨온 다음 그 행 또는 렬 을 한번 더 체크 해주어야 합니다 ( i++ )

 

 

- 자세한 것은 주석을 확인해주세요

 

 

 

3. 나의코드

 

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


int N,t,x,y;
int ground[10][10]; //0~9
int resultscore;
int resultblock;

void fillnemo() {
	if (t == 1) {
		for (int i = 4; i <=9; i++) { //파란색
			if (i == 9) { ground[x][i] = 1; break; }
			if (ground[x][i+1] == 1) { ground[x][i] = 1; break; }
		}
		for (int i = 4; i <= 9; i++) { //초록색
			if (i == 9) { ground[i][y] = 1; break; }
			if (ground[i+1][y] == 1) { ground[i][y] = 1; break; }
		}
	}
	else if (t == 2) {
		int tmpindex=10;
		for (int i = 4; i <= 9; i++) { //파란색
			if (ground[x][i] == 1 ) {
				tmpindex = i;
				break; }
		}
		ground[x][tmpindex - 1] = 1; ground[x][tmpindex - 2] = 1;

		tmpindex = 10;
		for (int i = 4; i <= 9; i++) { //초록색
			if (ground[i][y] == 1||ground[i][y+1]==1) {
				tmpindex = i;
				break;
			}
		}
		ground[tmpindex - 1][y] = 1; ground[tmpindex - 1][y + 1] = 1;
	}
	else {
		int tmpindex = 10;
		for (int i = 4; i <= 9; i++) { //파란색
			if (ground[x][i] == 1 || ground[x + 1][i] == 1) {
				tmpindex = i;
				break;
			}
		}
		ground[x][tmpindex - 1] = 1; ground[x + 1][tmpindex - 1] = 1;
		tmpindex = 10;
		for (int i = 4; i <= 9; i++) { //초록색
			if (ground[i][y] == 1 ) {
				tmpindex = i;
				break;
			}
		}
		ground[tmpindex - 1][y] = 1; ground[tmpindex - 2][y] = 1;
	}
}

void delblock() {
	//파란색
	for (int i = 9; i >= 6; i--) {
		bool checking = false;
		for (int j = 0; j < 4; j++) {
			if (ground[j][i] == 0) { checking = true; break; }
		}
		if (checking == false) { //4블록이 꽉찬경우
			resultscore++;
			for (int k = i; k >= 4; k--) { //이동시키기
				for (int l = 0; l < 4; l++) { ground[l][k] = ground[l][k-1]; }
			}
			i++; // 두줄이 한번에 꽉차는 경우를 위해서 이동시킨후 다시 그 행,렬부터 확인해야됨
		}
	}
	//초록색
	for (int i = 9; i >= 6; i--) {
		bool checking = false;
		for (int j = 0; j < 4; j++) {
			if (ground[i][j] == 0) { checking = true; break; }
		}
		if (checking == false) {
			resultscore++;
			for (int k = i; k >= 4; k--) { //이동시키기
				for (int l = 0; l < 4; l++) { ground[k][l] = ground[k-1][l]; }
			}
			i++; // 두줄이 한번에 꽉차는 경우를 위해서 이동시킨후 다시 그 행,렬부터 확인해야됨
		}
	}
}

void moveblock() { 
	//연한 파란색
	bool checking = false;
	int checkingcount = 0;
	for (int i = 4; i <= 5; i++) {
		for (int j = 0; j < 4; j++) {
			if (ground[j][i] == 1) { checkingcount++; break; }
		}
	}
	if (checkingcount != 0) {
		for (int i = 9; i >= 4; i--) {
			for (int j = 0; j < 4; j++) {
				ground[j][i] = ground[j][i - checkingcount];
			}
		}
	}
	for (int i = 4; i <= 5; i++) {
		for (int j = 0; j < 4; j++) {
			ground[j][i] = 0;
		}
	}
	//연한 초록색
	checking = false;
	checkingcount = 0;
	for (int i = 4; i <= 5; i++) {
		for (int j = 0; j < 4; j++) {
			if (ground[i][j] == 1) { checkingcount++; break; }
		}
	}
	if (checkingcount != 0) {
		for (int i = 9; i >= 4; i--) {
			for (int j = 0; j < 4; j++) {
				ground[i][j] = ground[i-checkingcount][j];
			}
		}
	}
	for (int i = 4; i <= 5; i++) {
		for (int j = 0; j < 4; j++) {
			ground[i][j] = 0;
		}
	}
}
void watchground() {
	cout << endl;
	for (int i = 0; i <= 9; i++) {
		for (int j = 0; j <= 9; j++) {
			cout << ground[i][j];
		}
		cout << endl;
	}
}
void getblock() {
	for (int i = 6; i <= 9; i++) {
		for (int j = 0; j < 4; j++) {
			if (ground[j][i] == true) resultblock++;
		}
	}
	for (int i = 6; i <= 9; i++) {
		for (int j = 0; j < 4; j++) {
			if (ground[i][j] == true) resultblock++;
		}
	}
}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	cin >> N;
	while (N--) {
		cin >> t >> x >> y;
		fillnemo(); // 블록 초록색 파란색으로 이동시키기
		delblock(); // 4블록이 꽉찬 행,또는 렬 삭제 (점수 획득)
		moveblock(); // 연한초록, 연한파란색에 블록이 있을 경우 이동
	}
	getblock();
	cout << resultscore << "\n";
	cout << resultblock << "\n";

	return 0;
}

 

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

백준 2726 [C++]  (0) 2021.01.16
백준 10993 [C++]  (0) 2021.01.16
백준 20056 [C++]  (0) 2020.12.23
백준 20055 [C++]  (0) 2020.12.23
백준 13458 [C++]  (0) 2020.12.15

www.acmicpc.net/problem/20056

 

20056번: 마법사 상어와 파이어볼

첫째 줄에 N, M, K가 주어진다. 둘째 줄부터 M개의 줄에 파이어볼의 정보가 한 줄에 하나씩 주어진다. 파이어볼의 정보는 다섯 정수 ri, ci, mi, si, di로 이루어져 있다. 서로 다른 두 파이어볼의 위치

www.acmicpc.net

1. 풀이방법

 

- 구현 문제이고 문제풀이에 필요한 알고리즘은 딱히 없습니다.

 

- 조건을 파악한뒤 이제 파이어볼이 이동할수 있는 지도가 연결되어 있다는 것이 중요한 것 같습니다.

 

- N을 넘어가면 다시 1로 오는 것이죠.

 

- 방향은 친절하게도 지도모양으로 줘서 8방향탐색 dx,dy를 설정해주시면 되고,

 

- 저같은 경우 파이어볼들을 저장하는 벡터 하나와 각 단계에서 ground[51][51]을 벡터로 선언해서,

 

- x,y에 이동한 파이어 볼이 있을경우 push_back으로 각 좌표에 매달아주는 느낌으로 구현하였습니다.

 

- 그렇게 파이어볼이 모두 이동시킨뒤 ground(맵)을 보면서 파이어볼이 없는 좌표는 continue

 

- 한개있는 좌표는 그대로 다시 totalfireball에 push, 두개 이상인 것은 문제 조건에 맞춰 재조정한후

 

- 4개의 파이어볼을 다시 totalfireball에 push 해주었습니다.

 

- 각 단계에서 vector들 clear()를 해주었구요.

 

 

 

 

2. 주의사항

 

- 이게 s(속력)이 최대 1000이 될수도 있습니다.

 

- 그래서 단순히 0보다 작아지면 N을 더해주거나 N보다 커지면 0으로 만들거나 하려면 이 자체도 반복문 처리를 해주어

 

- 합니다 그래서 그냥 아래와 같이 처리하였습니다.

 

- int newx = ((totalfireball[i].x) + dx[totalfireball[i].d] * totalfireball[i].s + 250 * N) % N;
  int newy = ((totalfireball[i].y) + dy[totalfireball[i].d] * totalfireball[i].s + 250 * N) % N;

 

- 250*N을 더해준 이유는 % 모듈러 연산을 할 때 음수가 나오는 것을 방지하기 위함인데

 

- N의 최솟값은 4이고 s의 최대값은 1000이므로 250*N은 1000보다 같거나 크면서 N 모듈러 연산에는 영향을 끼치지 

 

- 않는 수로 설정하였습니다(N의배수 이므로)

 

 

 

 

3. 나의코드

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

int N, M, K;
int dx[8] = { -1,-1,0,1,1,1,0,-1 };//8방향탐색
int dy[8] = { 0,1,1,1,0,-1,-1,-1 };

struct fireball {
	int x,y,m, s, d;
};
vector<fireball> ground[51][51];
vector<fireball> totalfireball;
void inputs() {
	cin >> N >> M >> K;
	int tx, ty, tm, ts, td;
	for(int i=0;i<M;i++){
		cin >> tx >> ty>>tm>>ts>>td;
		totalfireball.push_back({ tx-1,ty-1,tm,ts,td }); // 난 0~N-1
	}
}
void groundclear() {
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++) {
			ground[i][j].clear();
		}
	}
}
void moveball() {
	for (int i = 0; i < totalfireball.size(); i++) {
		int newx = ((totalfireball[i].x) + dx[totalfireball[i].d] * totalfireball[i].s + 250 * N) % N;
		int newy = ((totalfireball[i].y) + dy[totalfireball[i].d] * totalfireball[i].s + 250 * N) % N;
		ground[newx][newy].push_back({ newx,newy,totalfireball[i].m,totalfireball[i].s,totalfireball[i].d });
	}
}
void makenewball() {
	for(int i=0;i<N;i++){
		for (int j = 0; j < N; j++) {
			if (ground[i][j].empty()) continue; //비어있으면.
			else if (ground[i][j].size() == 1) { //파이어볼이 한개
				totalfireball.push_back(ground[i][j][0]);
			}
			else { //두개 이상인 경우
				int newm = 0; int news = 0;
				for (int k = 0; k < ground[i][j].size(); k++) {
					newm += ground[i][j][k].m;
					news += ground[i][j][k].s;
				}
				newm = newm / 5;
				if (newm == 0) continue;
				news = news / ground[i][j].size();


				bool check = false;
				for (int k = 0; k < ground[i][j].size(); k++) { //모두 홀수?
					if (ground[i][j][k].d % 2 == 0) { check = true; break; }
				}
				if (check == false) {
					totalfireball.push_back({ i,j,newm,news,0 });

					totalfireball.push_back({ i,j,newm,news,2 });

					totalfireball.push_back({ i,j,newm,news,4 });

					totalfireball.push_back({ i,j,newm,news,6 });
				continue;
				}

				check = false;
				for (int k = 0; k < ground[i][j].size(); k++) { //모두 짝수?
					if (ground[i][j][k].d % 2 == 1) { check = true; break; }
				}
				if (check == false) {
					totalfireball.push_back({ i,j,newm,news,0 });

					totalfireball.push_back({ i,j,newm,news,2 });

					totalfireball.push_back({ i,j,newm,news,4 });

					totalfireball.push_back({ i,j,newm,news,6 });
					continue;
				}
				// 둘다 아닐경우
				totalfireball.push_back({ i,j,newm,news,1 });

				totalfireball.push_back({ i,j,newm,news,3 });

				totalfireball.push_back({ i,j,newm,news,5 });

				totalfireball.push_back({ i,j,newm,news,7 });
			}
		}
	}
}
long long getm() {
	long long resultm = 0;
	for (int i = 0; i < totalfireball.size(); i++) {
		resultm += totalfireball[i].m;
	}
	return resultm;
}
int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	inputs();
	while (K--) {
		groundclear();
		moveball();
		totalfireball.clear();
		makenewball();
	}
	cout << getm() << "\n";


	return 0;
}

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

백준 10993 [C++]  (0) 2021.01.16
백준 20061 [C++]  (0) 2020.12.28
백준 20055 [C++]  (0) 2020.12.23
백준 13458 [C++]  (0) 2020.12.15
백준 15685 [C++]  (0) 2020.12.08

www.acmicpc.net/problem/20055

 

20055번: 컨베이어 벨트 위의 로봇

길이가 N인 컨베이어 벨트가 있고, 길이가 2N인 벨트가 이 컨베이어 벨트를 위아래로 감싸며 돌고 있다. 벨트는 길이 1 간격으로 2N개의 칸으로 나뉘어져 있으며, 각 칸에는 아래 그림과 같이 1부

www.acmicpc.net

1. 풀이방법

 

- 그냥 조건대로만 구현해 주시면 됩니다.

 

- 컨베이어 벨트는 문제그대로 N의 최대값인 200을 채우고 INDEX를 그대로 쓰려고 201로 선언해주었고

 

- bool 타입의 로봇배열을 그의 절반만 선언해서 벨트의 index와 같이 맞추어 위치를 index로 접근하였습니다.

 

 

2. 주의사항

 

- 굳이 이 문제를 블로그에 남기는 데에는 문제설명자체가 얼핏 잘못이해하기 쉬워서입니다.

 

- 일단 일반적인 우리의 생각으로는 당연히 컨베이어벨트가 한칸움직이면 위의 물건도 따라 움직입니다.

 

- 그리고 이문제에서는 그와 별개로 로봇도 움직일 수 있다. 라는 것이 이 문제입니다.

 

- 결국 일반적인 컨베이어벨트의 이동 + 로봇의 이동이 모두 들어간 문제입니다.

 

- 처음에는 문제의 조건을 읽고 일반적인 컨베이어벨트의 이동에 대한 설명은 없어서 그것을 제외하고 해야하나??

 

- 벨트는 벨트대로 움직이고 나서, 로봇의 이동을 하는 것인가 생각하였지만 그것은 아니였습니다.

 

- 물론 테스트케이스가 여러개라서 그것들을 통해서 위의 의문을 걸러낼 수 있습니다.

 

 

3. 나의코드

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

int N, K;
int zerocount;
int p = 0;
int barr[201];
bool robo[101];

void ratate() { //barr[0]는 그냥 tmp용으로 사용
	barr[0] = barr[2 * N];
	for (int i = 2 * N; i >= 2; i--) { //벨트이동
		barr[i] = barr[i - 1];
	}
	for (int i = N - 1; i >= 1; i--) { //로봇이동
		robo[i + 1] = robo[i];
	}
	robo[1] = false;
	barr[1] = barr[0];
}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	cin >> N >> K;
	for (int i = 1; i <= 2*N; i++) {
		cin >> barr[i];
		if (barr[i] == 0) zerocount++;
	}
	while (1) {
		if (zerocount >= K) break;
		p++;
		ratate();
		if (robo[N] == true) { //내려오는 칸
			robo[N]= false;
		}
		for (int i = N - 1;  i >= 1; i--) { //이동관련
			if (robo[i] == true) {
				if (robo[i + 1] == false && barr[i + 1] >= 1) {
					robo[i] = false; robo[i + 1] = true;
					barr[i + 1]--;
					if (barr[i + 1] == 0) zerocount++;
				}
			}
		}
		if (robo[1] == false && barr[1] >= 1) { //올라가는 칸
			robo[1] = true; barr[1]--;
			if (barr[1] == 0) zerocount++;
		}
	}
	cout << p << "\n";
	return 0;
}

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

백준 20061 [C++]  (0) 2020.12.28
백준 20056 [C++]  (0) 2020.12.23
백준 13458 [C++]  (0) 2020.12.15
백준 15685 [C++]  (0) 2020.12.08
백준 17144 [C++]  (0) 2020.12.08

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/13458

 

13458번: 시험 감독

첫째 줄에 시험장의 개수 N(1 ≤ N ≤ 1,000,000)이 주어진다. 둘째 줄에는 각 시험장에 있는 응시자의 수 Ai (1 ≤ Ai ≤ 1,000,000)가 주어진다. 셋째 줄에는 B와 C가 주어진다. (1 ≤ B, C ≤ 1,000,000)

www.acmicpc.net

1. 풀이방법

 

- 그냥 구현 문제입니다.

 

- "오직" 이라는 말이 약간 헷갈린다는 정도? 결국 모든 시험장에 총감독관은 1명 있어야 한다는 말입니다.

 

 

 

2. 주의사항

 

- 시험장이 최대 1,000,000 개 시험장당 응시자가 최대 1,000,000 입니다.

 

- 총,부 감독관 모두 1명씩만 감시가능 하다고 생각하면 1,000,000,000,000명이 필요할 수 있습니다.

 

- INT형으로는 부족 long long 자료형을 사용했습니다.

 

 

 

3. 나의코드

 

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

int N;
int B, C;
long long resultcount = 0;

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

	cin >> N;
	vector<int> examarea(N);
	for (int i = 0; i < N; i++) cin>>examarea[i];
	cin >> B >> C;

		for (int i = 0; i < N; i++) {
			resultcount++;
			examarea[i] -= B;
			if (examarea[i] <= 0) continue; //총 감독관 혼자 감시 가능
			else { 
				if (examarea[i] % C == 0) resultcount += (examarea[i] / C);
				else resultcount += ((examarea[i] / C) + 1); }
		}

	cout << resultcount << "\n";
	return 0;
}

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

백준 20056 [C++]  (0) 2020.12.23
백준 20055 [C++]  (0) 2020.12.23
백준 15685 [C++]  (0) 2020.12.08
백준 17144 [C++]  (0) 2020.12.08
백준 14499 [C++]  (0) 2020.12.08

+ Recent posts