문제 : https://www.acmicpc.net/problem/9093


[알고리즘풀이]

getline 함수를 이용해 띄어쓰기까지 포함해서 입력을 받고, buffer flush를 이용해 buffer를 비워준다.

#include<iostream>
#include<string>
#include<vector>

using namespace std;

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

	int t;
	cin >> t;
	string bufferflush;
	getline(cin, bufferflush);
	while (t--) {
		string input, temp;
		vector<string> s;
		getline(cin, input);
		for (int i = 0; i < input.length(); i++) {
			int start = i;
			while (i < input.length() && input[i] != ' ') {
				i++;
			}
			for (int j = i - 1; j >= start; j--) {
				cout << input[j];
			}
			if (i != input.length())
				cout << ' ';
			else
				cout << '\n';
		}
	}
}

 

'Problem Solving > ICPC' 카테고리의 다른 글

[ICPC][BOJ] 13335 - Trucks  (0) 2019.09.23
[ICPC][BOJ] 8912 - Sales  (0) 2019.09.23
[ACM-ICPC][BOJ] 8896 - Rock Paper Scissors  (0) 2019.09.04
[ACM-ICPC][BOJ] 10251 - Driving License  (0) 2019.08.27
[ACM-ICPC][BOJ] 9019 - DSLR  (0) 2019.08.16

문제 : https://www.acmicpc.net/problem/8896


[알고리즘풀이]

단순 구현 문제입니다.

각 라운드마다 가위, 바위, 보를 카운팅 한 후 각 경우마다 패배자를 Check해서 1명이 남을 때까지 라운드를 진행합니다.

#include<iostream>
#include<string>

using namespace std;

string list[11];

int main(void) {
	ios::sync_with_stdio(false);
	cin.tie(0);

	int t;
	cin >> t;
	while (t--) {
		int n;
		cin >> n;
		bool check[11] = {}; // i번째 선수가 졌으면 check[i] = true;
		bool flag = false;
		for (int i = 1; i <= n; i++)
			cin >> list[i];
		for (int i = 0; i < list[1].length(); i++) {
			bool RPS[3] = {}; // R P S 나온걸체크
			for (int j = 1; j <= n; j++) {
				if (check[j] == true) // 이미 기존에 진사람
					continue;
				if (list[j][i] == 'R')
					RPS[0] = true;
				if (list[j][i] == 'P')
					RPS[1] = true;
				if (list[j][i] == 'S')
					RPS[2] = true;
			}
			// R P S 가 다 나온 경우.
			if (RPS[0] && RPS[1] && RPS[2])
				continue;
			// R P 가 나온 경우
			if (RPS[0] && RPS[1] && !RPS[2]) {
				for (int j = 1; j <= n; j++)
					if (check[j] == false && list[j][i] == 'R')
						check[j] = true;
			}
			// R S 가 나온 경우
			if (RPS[0] && !RPS[1] && RPS[2]) {
				for (int j = 1; j <= n; j++)
					if (check[j] ==false && list[j][i] == 'S')
						check[j] = true;
			}
			// P S 가 나온 경우
			if (!RPS[0] && RPS[1] && RPS[2]) {
				for (int j = 1; j <= n; j++)
					if (check[j] == false && list[j][i] == 'P')
						check[j] = true;
			}
			int count = 0, index = 0;
			for (int j = 1; j <= n; j++) {
				if (check[j] == false) {
					count++;
					index = j;
				}
			}
			if (count == 1){
				cout << index << '\n';
				flag = true;

				break;
			}
		}
		if (!flag)
			cout << 0 << '\n';
	}
}

 

'Problem Solving > ICPC' 카테고리의 다른 글

[ICPC][BOJ] 8912 - Sales  (0) 2019.09.23
[ICPC][BOJ] 9093 - Word Reversal  (0) 2019.09.23
[ACM-ICPC][BOJ] 10251 - Driving License  (0) 2019.08.27
[ACM-ICPC][BOJ] 9019 - DSLR  (0) 2019.08.16
[ACM-ICPC][BOJ] 3758 - KCPC  (0) 2019.08.09

안녕하세요.

여행벌입니다.

오늘은 ACM-ICPC 2014 예선전 B번 문제인 Driving License 풀이를 해보겠습니다.

4차원 배열을 활용한 dp 문제로 어떻게 이런 아이디어를 내는지.. 정말 출제자나 푸신 분들이나 대단하네요...

저는 도저히 아이디어가 안 떠올라서 https://blog.encrypted.gg/86 님의 설명을 참고해서 문제를 풀었습니다.


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

불러오는 중입니다...

[알고리즘풀이]

이 문제의 핵심 힌트는 오른쪽 또는 아래로만 이동할 수 있고, 최소 이동 횟수는 오직 방향 전환(turn)에 의존하는 점입니다.

 

DP[i][j][k][d]  : (0,0) 부터 (i,j) 까지 k번 turn하고 d( 0 : 왼->오, 1 : 위->아래) 방향으로 왔을 때 최소 연료양

row[i][j] : i 번째 row 에서 j ~ j + 1 column까지 이동하는데 필요한 연료.

column[i][j] : i ~ i + 1 row까지  j 번째 column에서 이동하는데 필요한 연료.

 

다음과 같이배열을 정의한다. 그러면, 다음과 같은 방정식이 성립한다.

DP[i][j][k][0] = min(dp[i][j - 1][k][0] + row[i][j - 1], dp[i][j - 1][k - 1][1] + row[i][j - 1])

DP[i][j][k][1] = min(dp[i - 1][j][k][1] + column[i - 1][j], dp[i - 1][j][k - 1][0] + column[i - 1][j])

 

따라서 DP배열을 다 채우고나면 목표지점인 (N,M)에 대해 K 를 작은 값부터 순회하며, 기준 연료양보다 낮은 값을 발견하면 거리를 출력하면 된다.

 

#주의#

DP배열을 미리 큰 값으로 초기화하지 않으면, 기준 연료양보다 낮은 값이 DP[N][M][0][0] 에서 발견되므로 항상 큰 값들로 초기화해줘야 된다.

#include<iostream>
#include<algorithm>

using namespace std;

int dp[101][101][200][2];
int row[100][100];
int column[100][100];

int main(void) {
	ios::sync_with_stdio(false);
	cin.tie(0);

	int t;
	cin >> t;

	while (t--) {
		int r, c, l, g;
		cin >> r >> c >> l >> g;
		// row[i][j] 는 i 줄 j ~ j + 1까지의 연료.
		for (int i = 0; i < r; i++) {
			for (int j = 0; j < c - 1; j++)
				cin >> row[i][j];
		}
		// colum[i][j]는 i ~ i + 1 줄 j 의 연료.
		for (int i = 0; i < r - 1; i++)
			for (int j = 0; j < c; j++)
				cin >> column[i][j];

		int maxturn = 2 * max(r, c);
		// dp를 초기화시키자.
		for (int i = 0; i < r; i++)
			for (int j = 0; j < c; j++)
				for (int k = 0; k <= maxturn; k++)
					for (int l = 0; l < 2; l++)
						dp[i][j][k][l] = 99999999;
		dp[0][0][0][0] = 0, dp[0][0][0][1] = 0;
		// dp를 먼저 채워보자.
		for (int j = 1; j < c; j++)
			dp[0][j][0][0] = dp[0][j - 1][0][0] + row[0][j - 1];
		for (int i = 1; i < r; i++)
			dp[i][0][0][1] = dp[i - 1][0][0][1] + column[i - 1][0];
		// 나머지는 점화식을 활용해 채워보자.
		for (int i = 1; i < r; i++)
			for (int j = 1; j < c; j++) {
				maxturn = 2 * max(i, j);
				for (int k = 1; k <= maxturn; k++) {
					dp[i][j][k][0] = min(dp[i][j - 1][k][0] + row[i][j - 1], dp[i][j - 1][k - 1][1] + row[i][j - 1]);
					dp[i][j][k][1] = min(dp[i - 1][j][k][1] + column[i - 1][j], dp[i - 1][j][k - 1][0] + column[i - 1][j]);
				}
			}
		// 답을 도출해보자.
		bool flag = false;
		maxturn = 2 * max(r, c);
		for (int k = 0; k <= maxturn; k++) {
			if (dp[r - 1][c - 1][k][0] <= g || dp[r - 1][c - 1][k][1] <= g) {
				cout << l * (r - 1 + c - 1) + k << '\n';
				flag = true;
				break;
			}
		}
		if (!flag) {
			cout << "-1\n";
		}

	}
}

열심히 공부하고 노력하고 있는 꿈 많은 예비 개발자입니다.

혼자서 공부한 내용을 정리하고 포스팅하다 보니 틀린 내용이 있을 수도 있습니다.

많은 조언과 가르침 주실 분은 댓글로 자유롭게 남겨주셔도 좋을 것 같습니다! 

감사합니다.

'Problem Solving > ICPC' 카테고리의 다른 글

[ICPC][BOJ] 9093 - Word Reversal  (0) 2019.09.23
[ACM-ICPC][BOJ] 8896 - Rock Paper Scissors  (0) 2019.09.04
[ACM-ICPC][BOJ] 9019 - DSLR  (0) 2019.08.16
[ACM-ICPC][BOJ] 3758 - KCPC  (0) 2019.08.09
[ACM-ICPC][BOJ] 7287 - Registration  (0) 2019.08.08

안녕하세요.

여행벌입니다.


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

 

9019번: DSLR

문제 네 개의 명령어 D, S, L, R 을 이용하는 간단한 계산기가 있다. 이 계산기에는 레지스터가 하나 있는데, 이 레지스터에는 0 이상 10,000 미만의 십진수를 저장할 수 있다. 각 명령어는 이 레지스터에 저장된 n을 다음과 같이 변환한다. n의 네 자릿수를 d1, d2, d3, d4라고 하자(즉 n = ((d1 × 10 + d2) × 10 + d3) × 10 + d4라고 하자) D: D 는 n을 두 배로 바꾼다. 결과 값이 9999 보다 큰 경

www.acmicpc.net

[알고리즘설계]

1. A에서 시작해서 명령어 D / S / L / R  을 한 숫자가 아직 방문하지 않은 숫자라면 queue에 담아 가며 B가 나올 때까지 BFS 탐색을 진행한다. 이때, int path[10000], char answer[10001] 을 이용해서 방문 경로를 저장한다.

2. B에서 다시 방문 경로를 역 탐색하며 출력해준다.

#include<iostream>
#include<queue>

using namespace std;

char DSLR[5] = "DSLR";
void BFS(int, int);

int main(void) {
	ios::sync_with_stdio(false);
	cin.tie(0);

	int t;
	cin >> t;
	for (int i = 0; i < t; i++) {
		int A, B;
		cin >> A >> B;
		BFS(A,B);
	}
}

void BFS(int A, int B) {
	bool check[10000] = {};
	int npath[10000] = {};
	char cpath[10001] = {};
	queue<int> q;
	q.push(A);
	check[A] = true;
	while (!q.empty()) {
		int x = q.front(); q.pop();
		if (x == B) {
			vector<char>answer;
			while (x != A) {
				answer.push_back(cpath[x]);
				x = npath[x];
			}
			int length = (int)answer.size();
			for (int i = 0; i < length; i++)
				cout << answer[length - 1 - i];
			cout << '\n';
			return;
		}
		int list[4] = { (2 * x) % 10000, x - 1, (x % 1000) * 10 + x / 1000, (x % 10) * 1000 + x / 10 };
		if (list[1] < 0)
			list[1] = 9999;
		for (int i = 0; i < 4; i++) {
			if (!check[list[i]]) { // 지금 가려는 곳이 방문한 곳이 아니라면
				q.push(list[i]);
				check[list[i]] = true;
				npath[list[i]] = x;
				cpath[list[i]] = DSLR[i];
			}
		}

	}
}

코드는 간단하지만 구현하는데 정말 고생한 문제입니다...!


열심히 공부하고 노력하고 있는 꿈 많은 예비 개발자입니다.

혼자서 공부한 내용을 정리하고 포스팅하다 보니 틀린 내용이 있을 수도 있습니다.

많은 조언과 가르침 주실 분은 댓글로 자유롭게 남겨주셔도 좋을 것 같습니다! 

감사합니다.

 

'Problem Solving > ICPC' 카테고리의 다른 글

[ACM-ICPC][BOJ] 8896 - Rock Paper Scissors  (0) 2019.09.04
[ACM-ICPC][BOJ] 10251 - Driving License  (0) 2019.08.27
[ACM-ICPC][BOJ] 3758 - KCPC  (0) 2019.08.09
[ACM-ICPC][BOJ] 7287 - Registration  (0) 2019.08.08
[ACM-ICPC][BOJ] 9011 - Order  (0) 2019.08.08

+ Recent posts