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

 

1920번: 수 찾기

첫째 줄에 자연수 N(1 ≤ N ≤ 100,000)이 주어진다. 다음 줄에는 N개의 정수 A[1], A[2], …, A[N]이 주어진다. 다음 줄에는 M(1 ≤ M ≤ 100,000)이 주어진다. 다음 줄에는 M개의 수들이 주어지는데, 이 수들

www.acmicpc.net

1. 풀이방법

- N개의 수중에 주어지는 M개의 수들이 각각 존재하는 지 확인해야합니다

 

- 선형탐색을 진행할 경우 O(N*M) 이므로 약 10,000,000,000 는 시간초과에 걸릴 것 같습니다.

 

- O(NlogN) 정렬 + O(M*logN) 이분탐색 으로 해결했습니다.

 

 

 

2. 주의사항

- 조건으로 인한 시간초과

 

 

3. 나의코드

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

int Narr[100000];
int N, M;
bool existnum(int target) {
	int ep = N - 1;
	int sp = 0;
	int mid;
	while (sp<=ep) {
		mid = (sp + ep) / 2;
		if (Narr[mid] == target) { return true; }
		else if (Narr[mid] < target) {
			sp = mid + 1;
		}
		else if (Narr[mid] > target) {
			ep = mid - 1;
		}
	}
	return false;
}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	
	cin >> N;
	for (int i = 0; i < N; i++) {
		cin >> Narr[i];
	}
	sort(Narr, Narr+N); //이분탐색을 위한 정렬
	cin >> M;
	int target;
	for (int i = 0; i < M; i++) {
		cin >> target;
		cout << existnum(target)<<"\n";
	}
	return 0;
}

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

백준 2003 [C++]  (0) 2021.09.19
백준 3079 [C++]  (0) 2021.01.27
백준 2776 [C++]  (0) 2021.01.27
백준 2792 [C++]  (0) 2021.01.26
백준 1254 [C++]  (0) 2021.01.15

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

 

2003번: 수들의 합 2

첫째 줄에 N(1 ≤ N ≤ 10,000), M(1 ≤ M ≤ 300,000,000)이 주어진다. 다음 줄에는 A[1], A[2], …, A[N]이 공백으로 분리되어 주어진다. 각각의 A[x]는 30,000을 넘지 않는 자연수이다.

www.acmicpc.net

1. 풀이방법

- N의 숫자의 범위가 큰편입니다.

 

- O(N^2)은 100,000,000 시간제한 0.5초에 타임리밋 걸릴 수 있습니다.

 

- 투포인터를 이용해 한번의 순회로 해결했습니다.

 

- 단, 이는 A[i]가 자연수 (음수 아님) 조건이 있기 때문에 사용할 수 있습니다.

 

 

 

2. 주의사항

- 문제 조건을 정확히 파악해야 합니다.

 

 

3. 나의코드

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

int N, M;
vector<long long> arr;

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

	cin >> N >> M;
	long long tt;
	for (int i = 0; i < N; i++) {
		cin >> tt;
		arr.push_back(tt);
	}
	int tmpsum = arr[0];
	int resultcount = 0;
	int sp = 0;
	int ep = 0;
	while (1) {
		if (tmpsum == M) {
			resultcount++;
			tmpsum -= arr[sp];
			sp++;
			ep++;
			if (ep == N) break;
			tmpsum += arr[ep];
		}
		else if (tmpsum < M) {
			ep++;
			if (ep == N) break;
			tmpsum += arr[ep];
		}
		else if (tmpsum > M) {
			tmpsum -= arr[sp];
			sp++;
		}
	}
	cout << resultcount;
	return 0;
}

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

백준 1920 [C++]  (0) 2021.09.19
백준 3079 [C++]  (0) 2021.01.27
백준 2776 [C++]  (0) 2021.01.27
백준 2792 [C++]  (0) 2021.01.26
백준 1254 [C++]  (0) 2021.01.15

 

www.acmicpc.net/problem/19237

 

19237번: 어른 상어

첫 줄에는 N, M, k가 주어진다. (2 ≤ N ≤ 20, 2 ≤ M ≤ N2, 1 ≤ k ≤ 1,000) 그 다음 줄부터 N개의 줄에 걸쳐 격자의 모습이 주어진다. 0은 빈칸이고, 0이 아닌 수 x는 x번 상어가 들어있는 칸을 의미

www.acmicpc.net

1. 풀이방법

- 사실 풀이방법은 딱히 없습니다...

 

- 문제에서 원하는 조건 그대로를 구현해내면되고, 사용되는 알고리즘 또한 별로 없는 것 같다.

 

- 조건을 한단계씩 맞춰나가면서 스텝 바이 스텝으로 짜면 되는데,,,,,,,, 코드가 매우 길어집니다.. 저만 그런건지.....

 

 

 

2. 주의사항

- *** 처음에 문제를 천천히 파악하고 문제의 조건들을 충분히 담을 수 있을만한 자료구조와 변수 선언에 신경써야합니다.짜다 보니 이 변수들로만 모든걸 체크하기 부족해서 추가적으로 임의로 선언할 경우 코드가 길어지면서 실수할 가능성이 높은 것 같습니다.

 그래서 이 과정에 꽤 많은 시간을 소모해도 된다고 생각합니다.

 

 

- 단계,단계 차례대로 천천히 구현해 나갈 것

 

 

- 저 같은 경우 마지막에 다 짰는데도 틀렸습니다가 떠서 봤더니...

  비슷한 변수이름을 두개 (sharkdir, sharkdir) 을 선언해서 썼더니 코드가 길어지면서 저도 모르게 이를 실수 했습니다.

  왠만하면 변수이름은 잘 구별될 수 있도록 선언하는 것이 좋을 것 같습니다.

 

3. 나의코드

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

int n,m,k;
bool sharkdie[401];
vector<int> sharkdir;
pair<int, int> sharks[401]; //현재 상어들의 위치 (x,y)
vector<pair<int, int>> sea[21][21]; //first= 상어번호, second= 남은 k
int dirinfo[401][4][4];
int tmpint;
int dx[4] = { -1,1,0,0 };
int dy[4] = { 0,0,-1,1 };
//위.아래,왼쪽,오른쪽
void inputs() {
	cin >> n >> m >> k;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			cin >> tmpint;
			if (tmpint != 0) {
				sharks[tmpint].first = i; sharks[tmpint].second = j;
			}
		}
	}
	sharkdir.push_back(-1); // 인덱스 맞추기 용
	for (int i = 0; i < m; i++) {
		cin >> tmpint; sharkdir.push_back(tmpint-1); 
	}
	for (int i = 1; i <= m; i++) {
		for (int j = 0; j < 4; j++) {
			for (int k = 0; k < 4; k++) {
				cin >> tmpint;
				dirinfo[i][j][k]=tmpint-1;
			}
		}
	}
}
bool boundcheck(int x, int y) {
	return (x >= 0 && y >= 0 && x < n&& y < n);
}
bool checksharks() {
	for (int i = 2; i <= m; i++) {
		if (sharkdie[i] == false) return false;
	}
	return true; //1번 상어 빼고 다 쫓겨남
}
int main() {
	inputs();
	int resultsecond=0;
	while (1) {
		if (resultsecond > 1000) { cout << -1; break; }
		if (checksharks()) { cout << resultsecond; break; }


		//냄새 k 감소
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				if (!sea[i][j].empty()) {
					sea[i][j][0].second--;
					if (sea[i][j][0].second == 0) {
						sea[i][j].clear();
					}
}
			}
		}

		//냄새 뿌리기
		for (int i = 1; i <= m; i++) {
			if (sharkdie[i] == false) { //쫓겨나지 않았다면 냄새 뿌린다.
				sea[sharks[i].first][sharks[i].second].clear();
				sea[sharks[i].first][sharks[i].second].push_back({ i,k });
			}
		}

		//이동하기
		for (int i = 1; i <= m; i++) { //상어 한마리씩 본다.
			if (sharkdie[i] == true) continue;
			bool suc = false;
			// 냄새가 없는 칸이 있는지 먼저본다.
			for (int j = 0; j < 4; j++) {
				int nextx = sharks[i].first + dx[dirinfo[i][sharkdir[i]][j]];
				int nexty = sharks[i].second + dy[dirinfo[i][sharkdir[i]][j]];
				if (boundcheck(nextx, nexty) && sea[nextx][nexty].empty()) { //냄새가 없는 칸
					sharks[i].first = nextx;
					sharks[i].second = nexty;
					suc = true;
					sharkdir[i] = dirinfo[i][sharkdir[i]][j]; //이동한 방향이 보고있는 방향이 된다.
					break;
				}
			}
			
			if (suc == false) {
				for (int j = 0; j < 4; j++) {
					int nextx = sharks[i].first + dx[dirinfo[i][sharkdir[i]][j]];
					int nexty = sharks[i].second + dy[dirinfo[i][sharkdir[i]][j]];
					if (boundcheck(nextx, nexty) && sea[nextx][nexty][0].first == i) { //자신의 냄새가 있는 칸
						sharks[i].first = nextx;
						sharks[i].second = nexty;
						suc = true;
						sharkdir[i] = dirinfo[i][sharkdir[i]][j]; //이동한 방향이 보고있는 방향이 된다.
						break;
					}
				}
			}
		}



		// 겹치는 상어 쫓아내기
		for (int i = 1; i <= m; i++) {
			if (sharkdie[i] == true) continue;
			for (int j = i + 1; j <= m; j++) {
				if (sharkdie[j] == true) continue;
				if (sharks[i].first == sharks[j].first && sharks[i].second == sharks[j].second) { // 겹쳐진 상어가 생기면
					sharkdie[j] = true; // 쫓겨난다 (번호가 늦는 놈이)
				}
			}
		}
		resultsecond++;
	}
	return 0;
}

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

백준 16235 [C++]  (0) 2021.03.06
백준 17779 [C++]  (0) 2021.03.05
백준 17140 [C++]  (0) 2021.01.24
백준 2726 [C++]  (0) 2021.01.16
백준 10993 [C++]  (0) 2021.01.16

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

 

1107번: 리모컨

첫째 줄에 수빈이가 이동하려고 하는 채널 N (0 ≤ N ≤ 500,000)이 주어진다.  둘째 줄에는 고장난 버튼의 개수 M (0 ≤ M ≤ 10)이 주어진다. 고장난 버튼이 있는 경우에는 셋째 줄에는 고장난 버튼

www.acmicpc.net

1. 풀이방법

 

- 개인적으로 참 어려웠던 문제였습니다...

 

- 처음에는 경우의 수를 나눠서 1번 (+,-만으로만 접근) 2번 (버튼만으로 접근이 가능한 경우) 3번 (버튼으로 근접하게 간 후 +,- 로 이동해야하는 경우) 3가지 중 min 값을 출력하자 라고 했습니다.

 

- 하지만 저 3번....! 저걸 찾아내는게 굉장히 까다로웠습니다. 숫자를 하나씩 맞춰본다거나, 

  고장난 버튼이면 최대한 근접한 버튼을 누르는데 위,아래 어느 숫자쪽으로 탐색을 해야하나....

 

- 하나의 아이디어를 준 것은 바로 +,-는 마지막에 눌러진다는 것입니다. +,- 버튼을 누르고 나서 숫자를 누를경우 

  처음 부터 다시 숫자를 매겨야 하죠 (보통의 리모컨을 생각해 보시면 될 것 같습니다.)

 

- 그래서 생각해낸 것은 바로.....!

 

- 1. 일단 -1로 모든번호를 저장할 테이블들을 모두 초기화 ! (위로 갔다가 -로 돌아오는 경우도 있으므로 백만까지)

 

- 2. 버튼으로 이동할 수 있는 번호의 경우 테이블에 미리 다 몇번의 버튼을 눌러서 갈 수 있는지 저장!!!!

 

- 3. 찾고자 하는 채널이 -1, 즉 버튼만으로 갈 수 없는 경우 위,아래로 탐색해서 가장 가까이 있는 버튼으로 갈 수 있는

      번호를 찾는다 !!!!!!

( 물론 상기의 과정 중 +,- 버튼만으로 가는 것이 더 적은 수로 이동할 수 있는 경우 그 숫자를 넣어줘야 합니다.)

 

 

 

 

2. 주의사항

 

- 리모콘은 고장나면 쫌 사자.....

 

 

 

 

3. 나의코드

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

int N,M;
int remote[10]; //0~9
int casestore[1000001];
int len;

bool onlynum(int num) {
	len = 0;
	int tmp = num;
	while (1) {
		if (remote[tmp % 10] == true) return false; //고장나서 버튼만으로는 이동불가
		tmp /= 10;
		len++;
		if (tmp == 0) break;
	}
	return true;
}
void inputs() {
	cin >> N >> M;
	int tmp;
	for (int i = 0; i < M; i++) {
		cin >> tmp;
		remote[tmp] = true; //true는 고장
	}
}
void makecase() {
	casestore[100] = 0;
	for (int i = 0; i < 1000001; i++) {
		if (i == 100) continue;
		if(onlynum(i)==true)
		{
			casestore[i] = min(abs(i - 100), len);
		}
	}
}
void setcase() {
	for (int i = 0; i < 1000001; i++) {
		casestore[i] = -1;
	}
}


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

	if (N == 100) { cout << 0 << "\n"; return 0; }
	if(casestore[N]!=-1){
		cout << casestore[N] << "\n"; return 0;
	}
	else{
		int index = 1;
		while (1) {
			if (N - index >= 0) {
				if (casestore[N - index] != -1) {
					cout << min(abs(N - 100),casestore[N - index] + index) << "\n";
					return 0;
				}
			}
			if (N + index <= 1000000) {
				if (casestore[N + index] != -1) {
					cout << min(abs(N - 100),casestore[N + index] + index) << "\n";
					return 0;
				}
			}
			index++;
		}
	}
	return 0;
}

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

백준 18511 [C++]  (0) 2021.01.15
백준 9663 [C++]  (0) 2021.01.13
백준 14500 [C++]  (0) 2020.12.05
백준 17135 [C++]  (0) 2020.10.21
백준 17136 [C++]  (0) 2020.10.20

www.acmicpc.net/problem/11726

 

11726번: 2×n 타일링

2×n 크기의 직사각형을 1×2, 2×1 타일로 채우는 방법의 수를 구하는 프로그램을 작성하시오. 아래 그림은 2×5 크기의 직사각형을 채운 한 가지 방법의 예이다.

www.acmicpc.net

1. 풀이방법

- 이 문제를 접할 때 점화식을 생각해내는 게 생각보다 어려웠습니다.

 

- 물론 이런 류의 문제는 알고나면 매우 간단하기는 하지만......!

 

- 결국 점화식은 dp[n]=dp[n-1] + dp[n-2] 입니다 

 

- 그림을 보시면 이해가 쉬우실 듯 합니다.

 

 

2. 주의사항

 

- 값을 저장할 테이블을 구성해서 메모이제이션을 활용하여 시간을 단축시켜주었습니다.

 

- 탑다운 방식으로 재귀함수만을 이용하여 연산하는 경우 중복되는 연산을 너무나 많이 하기때문에

 

- TIME LIMIT을 만나실 수 있습니다.

 

- 저장되어있는값이 있으면 바로 리턴해서 가져다 쓰고 새로운 값이면 테이블에 저장을 한 후 리턴해서

 

- 다음부터는 그 값이 필요할 때 테이블에서 바로 가져다 쓸 수 있도록 하면 됩니다.

 

 

 

 

 

3. 나의코드

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

int  n;
int dp[1001];

int getdpvalue(int num) {
	if (dp[num] == 0) { 
		dp[num] = (getdpvalue(num - 1) % 10007 + getdpvalue(num - 2) % 10007);
		return dp[num] % 10007;
	}
	else return dp[num]%10007;
}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	cin >> n;
	dp[1] = 1; dp[2] = 2; dp[3] = 3; // 3을 초기화안해줘도 되긴하다
	                                 // (하지만 경우의수 그림 그려놨으니까..아까워서)
	cout<<getdpvalue(n)<<"\n";

	return 0;
}

'알고리즘 문제풀이 > 다이나믹 프로그래밍' 카테고리의 다른 글

백준 1463 [C++] - 메모리초과  (0) 2020.12.15
백준 11048 [C++]  (0) 2020.12.14
백준 7570 [C++]  (0) 2020.12.02
백준 12865 [C++]  (0) 2020.11.29
백준 1932  (0) 2020.03.02

www.acmicpc.net/problem/17144

 

17144번: 미세먼지 안녕!

미세먼지를 제거하기 위해 구사과는 공기청정기를 설치하려고 한다. 공기청정기의 성능을 테스트하기 위해 구사과는 집을 크기가 R×C인 격자판으로 나타냈고, 1×1 크기의 칸으로 나눴다. 구사

www.acmicpc.net

1. 풀이방법

 

- 온전한 구현문제 인 것 같습니다..

 

- 문제의 조건을 잘 파악하고 문제에서 원하는 대로 구현을 해주면 됩니다.

 

 

 

 

2. 주의사항

 

- 이 문제에서의 먼지가 퍼지는 것과 같이 가정상 한번에 쫙 퍼지는 것은 한좌표의 결과가 다른 좌표의 입력으로 들어가

   는 것을 조심해야 합니다.

 

- 저는 그래서 이전 단계의 좌표계 (roominfo)를 (copyroom)으로 복사해서 연산을 할 때는 copyroom으로 계산하고 결과를 roominfo에 넣었습니다.

 

 

 

3. 나의코드

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

int R, C, T;
int roominfo[51][51];
int copyroom[51][51];
int dx[4] = { 0,0,1,-1 }; //동서남북
int dy[4] = { 1,-1,0,0 };
int reverseclockx[4] = { 0,-1,0,1 }; //반시계
int reverseclocky[4] = { 1,0,-1,0 };
int clockx[4] = { 0,1,0,-1 }; //시계
int clocky[4] = { 1,0,-1,0 };
int dust;
vector<pair<int, int>> airfresh;

void inputs() {
	cin >> R >> C >> T;
	for (int i = 0; i < R; i++) {
		for (int j = 0; j < C; j++) {
			cin >> roominfo[i][j];
			if (roominfo[i][j] == -1) {
				pair<int, int> tmpp; tmpp.first = i; tmpp.second = j;
				airfresh.push_back(tmpp);
			}
		}
	}
}

void dustmove() { //먼지이동
	for (int a = 0; a < R; a++) {
		for (int b = 0; b < C; b++) {
			if (roominfo[a][b] == -1) continue;
			int movedust = 0;
			for (int i = 0; i < 4; i++) {
				if (a + dx[i] < 0 || a + dx[i] >= R || b + dy[i] < 0 || b + dy[i] >= C) continue;
				if (roominfo[a + dx[i]][b + dy[i]] == -1) continue;
				roominfo[a + dx[i]][b+dy[i]] += copyroom[a][b] / 5;
				movedust++;
			}
			roominfo[a][b] -= (copyroom[a][b] / 5)*movedust;
		}
	}

}

void airclean() { //순환(공기청정)
	int dir = 0;
	int tmp,tmp2;
	int nextX = airfresh[0].first + reverseclockx[dir]; int nextY = airfresh[0].second + reverseclocky[dir];
	tmp = roominfo[nextX][nextY];
	roominfo[nextX][nextY] = 0;
	while (1) { //위쪽(반시계)
		if (nextX + reverseclockx[dir] == airfresh[0].first &&nextY + reverseclocky[dir] == airfresh[0].second) break; //공기 청정기를 만남
		if (nextX + reverseclockx[dir] == R || nextX + reverseclockx[dir] == -1 || nextY + reverseclocky[dir] == -1 || nextY + reverseclocky[dir] == C) { dir++; continue; }
		nextX += reverseclockx[dir]; nextY += reverseclocky[dir];
		tmp2 = roominfo[nextX][nextY];
		roominfo[nextX][nextY] = tmp;
		tmp = tmp2;
	}
	             //아래쪽(시계)
	dir = 0;
	nextX = airfresh[1].first + clockx[dir];  nextY = airfresh[1].second + clocky[dir];
	tmp = roominfo[nextX][nextY];
	roominfo[nextX][nextY] = 0;
	while (1) {
		if (nextX + clockx[dir] == airfresh[1].first &&nextY + clocky[dir] == airfresh[1].second) break;//공기 청정기를 만남
		if (nextX + clockx[dir] == R || nextX + clockx[dir] == -1 || nextY + clocky[dir] == -1 || nextY + clocky[dir] == C) { dir++; continue; }
		nextX += clockx[dir]; nextY += clocky[dir];
		tmp2 = roominfo[nextX][nextY];
		roominfo[nextX][nextY] = tmp;
		tmp = tmp2;
	}
}
void getdust() {
	for (int i = 0; i < R; i++) {
		for (int j = 0; j < C; j++) {
			if (roominfo[i][j] > 0) dust += roominfo[i][j];
			}
		}
}
void copymap() {
	for (int i = 0; i < R; i++) {
		for (int j = 0; j < C; j++) {
			copyroom[i][j] = roominfo[i][j];
		}
	}
}
int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL); cout.tie(NULL);
	inputs();
	for (int i = 0; i < T; i++) {
		copymap();
		dustmove();
		airclean();
	}
	getdust();
	cout << dust << "\n";
	return 0;
}

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

백준 13458 [C++]  (0) 2020.12.15
백준 15685 [C++]  (0) 2020.12.08
백준 14499 [C++]  (0) 2020.12.08
백준 14503 [C++]  (0) 2020.12.08
백준 14891 [C++]  (0) 2020.12.06

+ Recent posts