www.acmicpc.net/problem/17837

 

17837번: 새로운 게임 2

재현이는 주변을 살펴보던 중 체스판과 말을 이용해서 새로운 게임을 만들기로 했다. 새로운 게임은 크기가 N×N인 체스판에서 진행되고, 사용하는 말의 개수는 K개이다. 말은 원판모양이고, 하

www.acmicpc.net

1. 풀이방법

- 구현문제입니다.

 

- 문제의 조건대로 출력해주면 됩니다.

 

- 자료형을 잘 생각해서 문제풀이 시작에 들어가면 됩니다.

 

 

 

2. 주의사항

- 아무리봐도 맞는데, 마지막 테케가 원하는 대로 안나오고 -1이 나왔습니다.

 

- 문제를 잘 읽어보니 종료조건을 TURN 이 증가 될때마다가 아닌, 한마리의 말을 이동시킬 때 마다 종료조건을 검사해야 합니다. 

 

-왜냐하면, 높이가 4이상이 되는 순간 (게임이 진행되는 도중) 바로 게임이 종료되기 때문입니다.

 

 

3. 나의 코드

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

int N, K;

int ground[14][14];
vector<pair<int,int>> chess[14][14]; //쌓이는 말들을 표시하기 위에 맨앞=맨아래 (번호, 이동방향)
vector<pair<int, int>> horse; //그말은 아니지만;;ㅎ

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

void inputs() {
	cin >> N >> K;
	for (int i = 0; i <= N + 1; i++) { //테두리는 파란색 취급
		ground[0][i] = 2;
		ground[i][0] = 2;
		ground[N + 1][i] = 2;
		ground[i][N + 1] = 2;
	}
	for (int i = 1; i <= N; i++) {
		for (int j = 1; j <= N; j++) {
			cin >> ground[i][j];
		}
	}
	horse.push_back({ -1,-1 }); //index 맞추기 용

	int x, y, z;
	for (int i = 1; i <= K; i++) {
		cin >> x >> y >> z;
		chess[x][y].push_back({ i, z-1 });
		horse.push_back({ x,y }); //말의 위치 표시
	}
}
bool checkexit() {
	for (int i = 1; i <= N; i++) {
		for (int j = 1; j <= N; j++) {
			if (chess[i][j].size() >= 4) return true;
		}
	}
	return false;
}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	inputs();
	int turncount = 0;
	while (1) {

		turncount++;
		//1번말부터 이동
		for (int i = 1; i <= K; i++) {
			int tx = horse[i].first; int ty = horse[i].second; // 그 말의 위치
			for (int j = 0; j < chess[tx][ty].size(); j++) {
				if (chess[tx][ty][j].first == i) { //쌓여있는 말의 위치를 알았다.

					int tmpdir = chess[tx][ty][j].second; //이동방향
					int nextx = tx + dx[tmpdir]; int nexty = ty + dy[tmpdir];


					if (ground[nextx][nexty] == 0) { //흰색
						int erasecount = 0;
						for (int k = j; k < chess[tx][ty].size(); k++) {
							chess[nextx][nexty].push_back(chess[tx][ty][k]);
							horse[chess[tx][ty][k].first] = { nextx,nexty }; //말의 위치가 바뀐걸 알려줘야 한다.
							erasecount++;
						}
						while (erasecount--) { //이동헀으니 제거
							chess[tx][ty].pop_back(); 
						}
						break;
					}

					else if (ground[nextx][nexty] == 1) { //빨간
						int erasecount = 0;
						for (int k = chess[tx][ty].size() - 1; k >= j; k--) {
							chess[nextx][nexty].push_back(chess[tx][ty][k]);
							horse[chess[tx][ty][k].first] = { nextx,nexty };
							erasecount++;
						}
						while (erasecount--) {
							chess[tx][ty].pop_back();
						}
						break;
					}
					else { //파란
						//이동방향 반대로

						if (tmpdir == 0) tmpdir = 1;
						else if (tmpdir == 1) tmpdir = 0;
						else if (tmpdir == 2) tmpdir = 3;
						else tmpdir = 2;

						chess[tx][ty][j].second = tmpdir;

						if (ground[tx + dx[tmpdir]][ty + dy[tmpdir]] == 2) { //반대도 파란색
							break;
						}
						else {
							j--;
						}// 한번 더 반복
					}
				}
			}
			//순간 이므로 !
			if (checkexit()) { cout << turncount; return 0; }
		}
		if (turncount > 1000) { cout << -1; return 0; }
	}
}

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

백준 17822 [C++]  (0) 2021.03.08
백준 17825 [C++]  (0) 2021.03.07
백준 16235 [C++]  (0) 2021.03.06
백준 17779 [C++]  (0) 2021.03.05
백준 19237 [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/17779

 

17779번: 게리맨더링 2

재현시의 시장 구재현은 지난 몇 년간 게리맨더링을 통해서 자신의 당에게 유리하게 선거구를 획정했다. 견제할 권력이 없어진 구재현은 권력을 매우 부당하게 행사했고, 심지어는 시의 이름

www.acmicpc.net

1. 풀이방법

- 구현문제입니다.

 

- 나머지 선거구는 문제에서 이미 범위가 다 주어져서 쉬운 문제입니다.

 

- 문제는 5번선거구를 처리하는 것입니다.

 

- 저는 가장자리를 먼저 구해서 맵에 체크 해놓고, (x+1,y) 좌표를 기준으로 bfs를 돌린 뒤, 4면이 다 5선거구로 둘러쌓여 있는 지역을 5번 선거구에 포함하여 주었습니다.

 

- 0 5 0 0 0

  5 0 5 0 0

  0 5 0 5 0

  0 0 5 0 0

 

- 위와 같은 예시는 4방향탐색 bfs로는 5선거구에 포함시킬 수 없기 때문입니다.

 

2. 주의사항

- 문제조건에 왠만하면 범위를 맞추자.... (0~n-1)로 고집하지말고... 1~n으로 맞춰서 하자....

 

 

3. 나의코드

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

pair<int, int> ground[22][22]; //first =선거구, second= 구역별 인원
int n;
queue<pair<int, int>> tmpq;
int dx[4] = { 0,0,1,-1 };
int dy[4] = { 1,-1,0,0 };
int numcount[6];
int resultmin = 20000;

void inputs() {
	cin >> n;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			cin >> ground[i][j].second;
		}
	}
}
bool boundcheck(int i, int j, int a, int b) {
	return ((i + a + b) <= n && (j - a >= 1) && (j + b <= n));
}
void initground() {
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			ground[i][j].first = 0;
		}
	}
}
bool bfsboundcheck(int x, int y) {
	return (x <= n&& x >= 1 && y >= 1 && y <= n);
}
void bfs(int x, int y) {
	ground[x][y].first = 5;
	tmpq.push({ x,y });
	while (!tmpq.empty()) {
		int qsize = tmpq.size();
		while (qsize--) {
			int nextx = tmpq.front().first;
			int nexty = tmpq.front().second;
			tmpq.pop();
			for (int i = 0; i < 4; i++) {
				int tx = nextx + dx[i];
				int ty = nexty + dy[i];
				if (bfsboundcheck(tx, ty) && ground[tx][ty].first != 5) {
					tmpq.push({ tx,ty });
					ground[tx][ty].first = 5;
				}
			}
		}
	}
}

void makeoutside(int x,int y,int d1,int d2) {
	// 일단 경계선
	for (int i = 0; i <= d1; i++) {
		ground[x + i][y - i].first = 5;
		ground[x + d2 + i][y + d2 - i].first = 5;
	}
	for (int j = 0; j <= d2; j++) {
		ground[x + j][y + j].first = 5;
		ground[x + d1 + j][y - d1 + j].first = 5;
	}
	//bfs 돌리고 + 4면이 모두 5인 곳은 따로 체크
	if (ground[x + 1][y].first == 0) bfs(x + 1, y);
	for (int i = 1; i < n; i++) {
		for (int j = 1; j < n; j++) {
			int tmpcount = 0;
			for (int k = 0; k < 4; k++) {
				if (ground[i + dx[k]][j + dy[k]].first == 5) {
					tmpcount++;
				}
				else break;
			}
			if (ground[i][j].first != 5 && tmpcount == 4) { ground[i][j].first = 5; }
		}
	}
	for (int i = 1; i < x + d1; i++) { //1번 선거구
		for (int j = 1; j <= y; j++) {
			if (ground[i][j].first == 5) continue;
			ground[i][j].first = 1;
		}
	}
	for (int i = 1; i <= x + d2; i++) { //2번 선거구
		for (int j = y+1; j <= n; j++) {
			if (ground[i][j].first == 5) continue;
			ground[i][j].first = 2;
		}
	}
	for (int i = x + d1; i <= n; i++) { //3번 선거구
		for (int j = 1; j < y - d1 + d2;j++) {
			if (ground[i][j].first == 5) continue;
			ground[i][j].first = 3;
		}
	}
	for (int i = x + d2+1; i <= n; i++) {
		for (int j = y - d1 + d2; j <= n; j++) {
			if (ground[i][j].first == 5) continue;
			ground[i][j].first = 4;
		}
	}
}
void numcheckreset() {
	for (int i = 1; i <= 5; i++) {
		numcount[i] = 0;
	}
}
void getnumcount() {
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			numcount[ground[i][j].first] += ground[i][j].second;
		}
	}
}
bool emptycheck() {
	for (int i = 1; i <= 5; i++) {
		if (numcount[i] == 0) return true;
	}
	return false;
}
int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	
	inputs();
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			for (int a = 1; a <= n; a++) {
				for (int b = 1; b <= n; b++) {
					if (boundcheck(i, j, a, b)) { //범위를 만족할 때만
						initground();
						makeoutside(i,j,a,b);
						numcheckreset();
						getnumcount();
						if (emptycheck()) continue; //적어도 하나의 구역 포함
						sort(numcount + 1, numcount + 6);
						resultmin = min(resultmin, numcount[5] - numcount[1]);
					}
				}
			}
		}
	}
	cout << resultmin;
	return 0;
}

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

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

 

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

 

1793번: 타일링

입력은 여러 개의 테스트 케이스로 이루어져 있다. 각 테스트 케이스는 한 줄로 이루어져 있으며, 숫자 0 ≤ n ≤ 250이 주어진다. 

www.acmicpc.net

1. 풀이방법

- 점화식을 찾는 것은 어렵지 않습니다.

 

- 그림 몇개 그려보고 생각 해보면 dp[i]=dp[i-1]+dp[i-2]*2 입니다.

 

- 하지만 더 큰 문제는 c++에서 제공해주는 정수 자료형으로는 이 문제의 출력을 담아 낼 수 없습니다.

 

- 그래서 저 같은 이차원으로 벡터를 이용해서 벡터의 한 원소당 한 자리의 숫자를 담아서 표현하였고,

 

- 점화식을 보면 기껏해야 2를 곱하는 것이기 때문에 이것은 그냥 더하기로 구현이 가능하기 때문에

 

- 큰 정수의 덧셈을 구하는 함수만 작성하여 해결하였습니다.

 

 

 

2. 주의사항

- 일단 dp[0]=1 입니다 (  nCo = 1 인 것과 같이) -- 아무것도 선택 안함

 

- 그리고 처음에 while(EOF) 를 이용하여 입력을 제어 했는데, 출력초과가 계속 나와서 

 

- 이부분을 , while (cin>>n)로 해결했습니다.

 

 

 

3. 나의코드

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




vector<int> bigintadd(vector<int> v1, vector<int> v2) {

	if (v1.size() < v2.size()) { // v1이 항상 더 큰수
		vector<int> tmpv = v1; v1 = v2; v2 = tmpv;
	}
	vector<int> result(v1.size());
	for (int i = 0; i < v1.size(); i++) {
		result[i] = 0;
	}
	if (v1.size() == v2.size() && (v1[v1.size() - 1] + v2[v2.size() - 1]) >= 10) {
		result.push_back(0); //사이즈 하나 증가
	}

	for (int i = 0; i < v2.size(); i++) {
		int tmpi = v1[i] + v2[i]+result[i];
		if (tmpi >= 10) { result[i + 1] += 1; result[i] =( tmpi-10); }
		else result[i] = tmpi;
	}
	for (int i = v2.size(); i < v1.size(); i++) {
		result[i] += v1[i];
	}

	return result;
}

// 점화식 dp[i]=dp[i-1]+dp[i-2]*(3-1)
// 큰수의 곱을 구현해야 한다.

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	vector<int> dp[251];
	dp[0].push_back(1); dp[1].push_back(1); dp[2].push_back(3);
	for (int i = 3; i <= 250; i++) {
		dp[i] = bigintadd(dp[i - 1], bigintadd(dp[i - 2], dp[i - 2])); //8은 171 7은 85   171+85+85
	}
	int n;
	while (cin>>n) {
		for (int i = dp[n].size() - 1; i >= 0; i--) {
			cout << dp[n][i];
		}
		cout << "\n";
	}
	return 0;
}

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

백준 3687 [C++]  (0) 2021.08.09
백준 1103 [C++]  (0) 2021.07.06
백준 1965 [C++]  (0) 2021.02.03
백준 1463 [C++] - 메모리초과  (0) 2020.12.15
백준 11048 [C++]  (0) 2020.12.14

www.acmicpc.net/problem/1965

 

1965번: 상자넣기

정육면체 모양의 상자가 일렬로 늘어서 있다. 상자마다 크기가 주어져 있는데, 앞에 있는 상자의 크기가 뒤에 있는 상자의 크기보다 작으면, 앞에 있는 상자를 뒤에 있는 상자 안에 넣을 수가

www.acmicpc.net

1. 풀이방법

 

- 간단하게 생각하면 매우 간단합니다. 

 

- 저 같은 경우 처음에 막혔던 부분이 보통의 dp문제에서 dp테이블은 각각의 n에 따른 정답? 을 가지고 있습니다.

 

- 이런식으로 짜려고 고민을 하다 보니 상당히 구현이 까다로웠습니다.

 

- 예를 들면 테스트케이스 가 1, 6, 2, 5, 7, 3, 5, 6   총 8개 인데

 

- 보통의 dp 테이블이면 만약 dp[6]을 뽑으면 최대치는 1,2,5,7 로서 4가 나와야 하고 

 

- 이때의 상자의 바깥껍질의 크기인 7을 저장하면 dp[7]을 구하려고 할 때 1,2,5,7,과 1,2,3, +5 를 비교하는 것이 힘들었습니다.

 

- 설명하기가 조금 곤란한데, 비슷한 고민을 하신 분들은 공감을 하시리라....조심스럽게 생각해봅니다....

 

- 그래서 이 문제의 경우 n이하의 각각의 정답(즉 최대 상자의 수)를 dp에 저장하는 것이 아니라 

 

- n에 크기를 늘려가면서 그때까지 차곡차곡 쌓기만한 크기를 저장해 놓은 다음 출력 전에 정렬을 해서 max 값을 

 

- 출력하였습니다. 물론 정렬(소팅)을 하지않고 최대값만 갱신해도 상관 없습니다.

 

- 이런식으로 할경우 사실 정렬 전에 dp[6]에는 상자의 개수 3 (1,2,3) dp[5]에는 4 (1,2,5,7) 이 들어가 있습니다.

 

- 그러므로 n이 6일 때의 정답이 테이블에 들어가 있는 것은 아닌 것이죠. 정렬을 해서 출력을 해줘야 정답이 나오는 

 

- 것 입니다. 하지만 이렇게 하면 문제의 요구사항에는 전혀 에러가 없고, 구현이 편해집니다.

 

 

 

2. 주의사항

 

- 위에 기재.

 

 

3. 나의코드

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

int dp[1001]; // 사실상 정확한 dp를 가지고 있는 테이블은 아니다.
int n;
int narr[1001]; //상자의 크기


int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	cin >> n;
	for (int i = 1; i <= n; i++) { //초기화
		cin >> narr[i]; dp[i] = 1;
	}
	for (int i = 2; i <= n; i++) {
		for (int j = 1; j < i; j++) {
			if (narr[i] > narr[j] && dp[i]<dp[j]+1) {
				dp[i] = dp[j]+ 1;
			}
		}
	}
	sort(dp + 1, dp + (n + 1));
	cout << dp[n];

	return 0;
}

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

백준 1103 [C++]  (0) 2021.07.06
백준 1793 [C++]  (0) 2021.02.04
백준 1463 [C++] - 메모리초과  (0) 2020.12.15
백준 11048 [C++]  (0) 2020.12.14
백준 11726 [C++]  (0) 2020.12.14

www.acmicpc.net/problem/3079

 

3079번: 입국심사

첫째 줄에 N과 M이 주어진다. (1 ≤ N ≤ 100,000, 1 ≤ M ≤ 1,000,000,000) 다음 N개 줄에는 각 심사대에서 심사를 하는데 걸리는 시간인 Tk가 주어진다. (1 ≤ Tk ≤ 109)

www.acmicpc.net

1. 풀이방법

 

- 일단, 문제를 보시면 M (친구들의 수) 가 매우 큽니다

 

- M배열같은경우 원소 하나씩 처리 (뭐 친구를 한명씩 심사대에 넣어본다거나)

 

- 이렇게 선형탐색만 해도 시간초과가 날 것입니다.  --> 이런방식은 안됨

 

- 그럼 주어진 배열의 값들로 탐색하는 것이 아닌 최소시간과 최대시간을 가지고 시간이라는 요소를 가지고 

 

- 이분탐색을 수행합니다.

 

- 시간이 주어졌을때 (시간) / (각각의 심사대에서 걸리는 시간) 을 하면 몇명을 심사할 수 있는지가 나오고

 

- 이것들을 더했을 때 주어진 시간에서의 (총 심사가능인원수)가 나오는데 이 인원이

 

- 친구들의 수 M보다 크면 심사가 되는 것이므로 결과값과 비교를 통해 넣어주고 더 적은 시간으로 가능한지를

 

- 탐색하러 떠납니다.

 

 

 

 

2. 주의사항

 

- 이분탐색 문제가 익숙치 않아서 그런지 좀 생각하는데 시간이 걸리는 것 같습니다.

 

- 그래도 저번에 www.acmicpc.net/problem/2792 (보석상자) 문제를 풀고난 후 라 조금 수월했던 것 같습니다.

 

 

 

3. 나의코드

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

long long n, m,tmp;
vector<long long> commitarr;
long long resulttime=1e18;
void inputs() {
	cin >> n >> m; //n개의 심사대 , m 명의 친구들
	for (int i = 0; i < n; i++) {
		cin >> tmp; commitarr.push_back(tmp);
	}
}

void findtime(long long l, long long h)
{
	if (l > h) return;
	long long mid = (l + h) / 2;
	long long tmpsum = 0;
	for (int i = 0; i < n; i++) {
		tmpsum += (mid / commitarr[i]); //시간동안 각각의 심사대에서 심사가능인원
	}
	if (tmpsum >= m) {
		if (resulttime > mid) { resulttime = mid; } //더 적은시간으로 가능하면 갱신
		findtime(l, mid - 1);
	}
	else findtime(mid + 1, h);

}
int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	inputs();
	sort(commitarr.begin(), commitarr.end());
	long long lowtime = 1; long long hightime = commitarr[n - 1] * m;
	//가장 오래걸리는 심사대에서 모두 받을 경우가 최대
	findtime(lowtime, hightime);
	cout << resulttime;
	return 0;
}

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

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

www.acmicpc.net/problem/2776

 

2776번: 암기왕

연종이는 엄청난 기억력을 가지고 있다. 그래서 하루 동안 본 정수들을 모두 기억 할 수 있다. 하지만 이를 믿을 수 없는 동규는 그의 기억력을 시험해 보기로 한다. 동규는 연종을 따라 다니며,

www.acmicpc.net

1. 풀이방법

 

- 시간제한은 2초 

 

- N,M 모두 최대 1,000,000 이므로 M배열의 각각의 원소에 대해 N배열을 선형탐색하면 시간초과가 발생

 

- N배열을 정렬하고 (c++ stl에서 제공하는 sort함수는 O(nlogn)을 보장해줍니다.

 

- 그후 M배열 각각의 원소로 N배열에 대해서 이분탐색을 진행 하시면 됩니다.

 

- 재귀, 반복문 다 구현 가능하며 저는 이 문제는 while문으로 구현하였습니다.

 

 

 

2. 주의사항

 

- 시간초과

 

 

 

3. 나의코드

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



int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	int t, n, m;
	cin >> t;
	while (t--) {
		cin >> n;
		vector<int> narr(n);
		for (int i = 0; i < n; i++) cin >> narr[i];
		sort(narr.begin(), narr.end()); // 정렬

		cin >> m;
		vector<int> marr(m);
		for (int i = 0; i < m; i++) cin >> marr[i];

		for (int i = 0; i < m; i++) { //수첩 2
			int lowindex = 0; int highindex = n - 1;
			while (1) {
				if (lowindex > highindex) { cout << 0<<"\n"; break;}
				int midindex = (lowindex + highindex) / 2;
				if (narr[midindex] == marr[i]) {cout << 1 << "\n"; break;}

				if (narr[midindex] > marr[i]) {
					highindex = midindex - 1;
				}
				else {
					lowindex = midindex + 1;
				}
			}
		}
	}
	return 0;
}

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

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

+ Recent posts