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


[알고리즘풀이]

중복을 허락하지 않으면서 모든 경우를 뽑아야 하므로, 방문한 지점을 체크하는 배열을 활용한 백트레킹 기법으로 문제를 해결한다.

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

int n, m;
bool visited[9];
vector<int> v;
void bt(int);

int main(void) {
	cin >> n >> m;
	bt(0);
}

void bt(int cnt) {
	if (cnt == m) {
		for (int i = 0; i < m; i++)
			cout << v[i] << ' ';
		cout << '\n';
		return;
	}
	for (int i = 1; i <= n; i++) {
		if(!visited[i]){
			visited[i] = true;
			v.push_back(i);
			bt(cnt + 1);
			visited[i] = false;
			v.pop_back();
		}
	}
}

 

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

[BOJ] 15651 - N 과 M (3)  (0) 2019.09.08
[BOJ] 15650 - N 과 M (2)  (0) 2019.09.08
[BOJ] 2240 - 자두나무  (0) 2019.09.04
[BOJ] 1937 - 욕심쟁이 판다  (0) 2019.09.03
[BOJ] 2156 - 포도주 시식  (0) 2019.09.03

문제 : 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

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

 

2240번: 자두나무

자두는 자두를 좋아한다. 그래서 집에 자두나무를 심어두고, 여기서 열리는 자두를 먹고는 한다. 하지만 자두는 키가 작아서 자두를 따먹지는 못하고, 자두가 떨어질 때까지 기다린 다음에 떨어지는 자두를 받아서 먹고는 한다. 자두를 잡을 때에는 자두가 허공에 있을 때 잡아야 하는데, 이는 자두가 말랑말랑하여 바닥에 떨어지면 못 먹을 정도로 뭉개지기 때문이다. 매 초마다, 두 개의 나무 중 하나의 나무에서 열매가 떨어지게 된다. 만약 열매가 떨어지는 순간, 자두

www.acmicpc.net


[알고리즘풀이]

t[x] : x 초에 떨어지는 자두의 위치. ( 1이면 1번 나무, 2이면 2번 나무 )

dp[x][y][z] : x 초까지 y 번 방향을 전환했고 현재 z 위치에서 최댓값.

( z 가 0일 때 1번 나무, 1일 때 2번 나무라고 정의 )

 

-초기값

dp[x][0][0] : x 초에 0번 방향을 전환했고 1번 나무 위치에서 최댓값.

               = 1번 나무에서 지금까지 떨어진 자두의 수 ( 방향 전환 없으므로 1번 나무에서 계속 있었다. )

 

dp[x][1][1] : x 초에 1번 방향을 전환했고 2번 나무 위치에서 최댓값.

               = ( x - 1 초에서 0번 방향을 전환했고, 1번 나무 위치에서 최댓값 , x - 1 초에서 1번 방향을 전환했고,

                   2번 나 무 위치에서 최대값 ) 중 더 큰 값에 t[x] 가 2라면 + 1을 해준다.

-점화식

dp[x][y][0] = max(dp[x-1][y-1][1], dp[x-1][y][0]) 에 t[x] 가 1이라면 1을 더해준다.

dp[x][y][1] = max(dp[x-1][y-1][0], dp[x-1][y][1]) 에 t[x] 가 2라면 1을 더해준다.

 

#include<iostream>
#include<algorithm>

using namespace std;

int t[1001];
int n, m;
int dp[1001][31][2];

int main(void) {
	ios::sync_with_stdio(false);
	cin.tie(0);
	// 입력
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		cin >> t[i];
	}
	// 초기값
	for (int i = 1; i <= n; i++) {
		dp[i][0][0] = dp[i - 1][0][0];
		dp[i][1][1] = max(dp[i - 1][1][1], dp[i - 1][0][0]);
		if (t[i] == 1)
			dp[i][0][0]++;
		if (t[i] == 2)
			dp[i][1][1]++;
	}
	// 점화식
	for (int i = 2; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			dp[i][j][0] = max(dp[i - 1][j - 1][1], dp[i - 1][j][0]);
			dp[i][j][1] = max(dp[i - 1][j - 1][0], dp[i - 1][j][1]);
			if (t[i] == 1)
				dp[i][j][0]++;
			else
				dp[i][j][1]++;
		}
	}
	int result = 0;
	for (int j = 0; j <= m; j++)
		for (int k = 0; k < 2; k++)
			if (dp[n][j][k] > result)
				result = dp[n][j][k];
	cout << result;
}

 

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

[BOJ] 15650 - N 과 M (2)  (0) 2019.09.08
[BOJ] 15469 - N 과 M (1)  (0) 2019.09.08
[BOJ] 1937 - 욕심쟁이 판다  (0) 2019.09.03
[BOJ] 2156 - 포도주 시식  (0) 2019.09.03
[BOJ] 10844 - 쉬운 계단 수  (0) 2019.09.03

안녕하세요.
여행벌입니다.

오늘은 BOJ 1937번 욕심쟁이 판다 문제를 다뤄보겠습니다.

Dp 와 DFS 를 조합해야 해결할 수 있는 문제로 까다로운 문제입니다.


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

 

1937번: 욕심쟁이 판다

n*n의 크기의 대나무 숲이 있다. 욕심쟁이 판다는 어떤 지역에서 대나무를 먹기 시작한다. 그리고 그 곳의 대나무를 다 먹어 치우면 상, 하, 좌, 우 중 한 곳으로 이동을 한다. 그리고 또 그곳에서 대나무를 먹는다. 그런데 단 조건이 있다. 이 판다는 매우 욕심이 많아서 대나무를 먹고 자리를 옮기면 그 옮긴 지역에 그 전 지역보다 대나무가 많이 있어야 한다. 만약에 그런 지점이 없으면 이 판다는 불만을 가지고 단식 투쟁을 하다가 죽게 된다(-_-) 이

www.acmicpc.net

[알고리즘풀이]

가장 먼저 생각나는 방법은 모든 곳에서 DFS 탐색을 진행하며, 가장 오래 살아남는 값을 구하는 방법입니다.

단순하고 정확하지만 시간초과에 걸립니다.

따라서 DFS 탐색을 진행하며, 더 이상 탐색을 진행하지 않아도 되는 경우에 한해서는 가지치기를 해줘야 합니다.

이를 위해 메모이제이션을 이용합니다.

똑같이 모든 곳에서 DFS 탐색을 진행해나가는데, DFS 탐색을 하며 그 지점에서 가장 오래 살아남는 값을 저장해나갑니다.

그러다 이미 탐색이 완료된 지점(값을 저장한 곳)에 방문하게 되면 더 이상 탐색을 진행하지 않고도

가장 오래 살아남는 값을 도출해낼 수 있으므로 탐색을 종료하면 됩니다.

#include<iostream>
#include<algorithm>

using namespace std;

int n;
int map[500][500];
int dp[500][500];

int d_x[4] = { -1,0,1,0 };
int d_y[4] = { 0,-1,0,1 };

int DFS(int, int);

int main(void) {
	cin >> n;
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++)
			cin >> map[i][j];

	int ans = 0;
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++)
			ans = max(ans, DFS(i, j)); // 지금까지 나온 값 중 가장 큰 값을 저장.
	cout << ans;
}

int DFS(int x, int y) {
	if (dp[x][y]) // 이미 탐색이 완료된 지점이라면 종료
		return dp[x][y];
	dp[x][y] = 1; // 아니라면 1부터 탐색 진행.
	for (int i = 0; i < 4; i++) {
		int n_x = x + d_x[i], n_y = y + d_y[i];
		if (0 <= n_x && n_x < n && 0 <= n_y && n_y < n)
			if (map[x][y] < map[n_x][n_y])
				dp[x][y] = max(dp[x][y], DFS(n_x, n_y) + 1);
	}
	return dp[x][y];
}

 

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

[BOJ] 15469 - N 과 M (1)  (0) 2019.09.08
[BOJ] 2240 - 자두나무  (0) 2019.09.04
[BOJ] 2156 - 포도주 시식  (0) 2019.09.03
[BOJ] 10844 - 쉬운 계단 수  (0) 2019.09.03
[BOJ] 4949 - The Balance of the World  (0) 2019.09.02

+ Recent posts