링크 : 2512번: 예산 (acmicpc.net)

 

2512번: 예산

첫째 줄에는 지방의 수를 의미하는 정수 N이 주어진다. N은 3 이상 10,000 이하이다. 다음 줄에는 각 지방의 예산요청을 표현하는 N개의 정수가 빈칸을 사이에 두고 주어진다. 이 값들은 모두 1 이상

www.acmicpc.net

코드 :

import sys
input = sys.stdin.readline
N = int(input())
member = list(map(int, input().split()))
total_money = int(input())
start = 0
end = max(member)

mid = 0
mid_val = 0

while (start <= end):
    mid = int((start + end) / 2)
    sum = 0
    for i in range(0, len(member)):
        sum += min(member[i], mid)

    if (sum > total_money):
        end = mid - 1
    else:
        start = mid + 1
        mid_val = max(mid_val, mid)
        #print(mid_val)

print(mid_val)

 

  1. 상한선을 잘 선택해야 풀 수 있는 문제였습니다.
  2. 상한선 선택은 이진탐색으로 진행합니다.
  3. 상한선을 선택했다면 min 함수를 이용해 지방에게 줄 돈을 선정합니다.
  4. 만일 상한선보다 작은 요청금액이라면 요청금액대로 줄 것이고, 상한선보다 큰 요청금액이라면 상한선만큼 줍니다. 이 때 내어준 총 금액은 sum 변수에 저장합니다.
  5. sum 변수가 줄 수 있는 금액보다 크다면 배제합니다.
  6. sum 변수가 줄 수 있는 금액보다 크거나 작다면 해당 상한선을 저장하고, 이 상한선보다 더 큰 상한선이 있는지 mid를 조정하며 찾습니다.

'문제풀이 > 백준' 카테고리의 다른 글

2116 - 주사위 쌓기  (0) 2023.06.01
12904 - A와 B  (0) 2023.05.21
15654 - N과 M (5)  (0) 2023.01.23
2529 - 부등호  (0) 2023.01.17
2636 - 치즈  (0) 2023.01.12

문제 :

2116번: 주사위 쌓기 (acmicpc.net)

 

2116번: 주사위 쌓기

첫줄에는 주사위의 개수가 입력된다. 그 다음 줄부터는 한 줄에 하나씩 주사위의 종류가 1번 주사위부터 주사위 번호 순서대로 입력된다. 주사위의 종류는 각 면에 적혀진 숫자가 그림1에 있는

www.acmicpc.net

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

#define MAX_SQUARE_MAX_CNT (10000 + 1)
#define dice_kind_cnt      (6 + 1)
vector<uint32_t>         square_vec[MAX_SQUARE_MAX_CNT];
uint32_t                 square_cnt;
uint32_t                 max_ans                         = 0;
uint32_t                 maxNum_arry[MAX_SQUARE_MAX_CNT] = {0};
uint32_t                 compatible[6 + 1]               = {0};

void Run(const uint32_t under_num, const uint32_t curr_layer,
              uint32_t sum) {
    if (curr_layer > square_cnt) {
        if (max_ans < sum) {
            max_ans = sum;
        }

        return;
    }

    uint32_t upper_num     = 0;
    for (int i = 1; i <= 6; i++) {
        if (square_vec[curr_layer][i] == under_num) {
            upper_num = square_vec[curr_layer][compatible[i]];
            break;
        }
    }

    int nowmax = 6;
    while (true) { // 지금 행에서 옆면최대값 찾는 과정
        if (nowmax != upper_num && nowmax != under_num)
            break;
        else
            nowmax--;
    }

    Run(upper_num, curr_layer + 1,
        sum + nowmax);
}

int main(void) {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cin >> square_cnt;
    for (size_t i = 1; i <= square_cnt; ++i) {
        square_vec[i].resize(7);
        for (uint32_t j = 1; j <= 6; j++) {
            uint32_t temp;
            cin >> square_vec[i][j];
        }
    }

    compatible[1] = 6, compatible[6] = 1;
    compatible[2] = 4, compatible[4] = 2;
    compatible[3] = 5, compatible[5] = 3;

    // 어느면이 윗면인지 고려되있지 않음.
    for (size_t i = 1; i <= 6; i++) {
        Run(square_vec[1][i], 1, 0);
    }

	cout << max_ans << '\n';

    return 0;
}

초등학생 수준의 문제라니.... 예제는 맞았지만, 정답은 아니었어서 아래 링크의 코드를 참고했습니다. 제 아이디어와 동일했지만, 제 코드는 답이 아니었어서... ㅜ

백준2116-주사위쌓기 java (tistory.com)

문제를 정확히 이해하지 못해, 처음엔 아예 틀린 방법으로 접근했었네요. 그래서 정답이 계속 30이 나왔었지만, 힌트를 보고 그게 아닌것을 알았습니다.

아랫면의 숫자와 매칭되는 숫자가 다음 층의 주사위의 아랫면이 된다는 것을 유념하시면 됩니다.

'문제풀이 > 백준' 카테고리의 다른 글

2512 - 예산  (0) 2023.09.02
12904 - A와 B  (0) 2023.05.21
15654 - N과 M (5)  (0) 2023.01.23
2529 - 부등호  (0) 2023.01.17
2636 - 치즈  (0) 2023.01.12
import sys

def run():
    src_str = input()
    dst_str = input()

    for i in range(0, len(dst_str)):
        if (src_str == dst_str):
            print(1)
            return
        
        if dst_str[len(dst_str) - 1]   ==  'A':
            dst_str = dst_str[0:len(dst_str) - 1]
        else:
            dst_str = dst_str[0:len(dst_str) - 1]
            dst_str = dst_str[::-1]

    print(0)

run()

문제 :

12904번: A와 B (acmicpc.net)

 

12904번: A와 B

수빈이는 A와 B로만 이루어진 영어 단어가 존재한다는 사실에 놀랐다. 대표적인 예로 AB (Abdominal의 약자), BAA (양의 울음 소리), AA (용암의 종류), ABBA (스웨덴 팝 그룹)이 있다. 이런 사실에 놀란 수

www.acmicpc.net

 

  1. src 스트링에서 dst 스트링으로 바꿀 수 있는지 확인하는 문제였습니다.
  2. src 스트링에서 dst 스트링으로 바꾸려고하면 많은 경우의 수 때문에 시간 초과가 발생하게 됩니다.
  3. 따라서 dst 스트링에서 src으로 바꿀 수 있는지를 확인합니다.
  4. dst 스트링에서 src 스트링으로 바꾸더라도, 결국 src에서 dst로 바꾸는거와 다르지 않냐라고 생각할 수 있습니다.
  5. 하지만 dst에서 src로 바꾸는것은 dst에서 src로 바꿀 수 있다는 전제를 두고 진행합니다.
  6. 따라서 1번 2번 연산을 거꾸로 해주기만 하면 됩니다.
  7. ABBA의 경우입니다.
    • 끝이 A이기 때문에 A를 삭제합니다. -> ABB
    • 끝이 B이기 때문에 B를 삭제하고 순서를 뒤집습니다. -> AB -> BA
    • 끝이 A이기 때문에 A를 삭제합니다. -> B
  8. B가 나왔습니다.
  9. 위와 같이 진행해서 dst에서 src로 변환 안되면 0을 출력 그렇지않다면 1을 출력합니다.

'문제풀이 > 백준' 카테고리의 다른 글

2512 - 예산  (0) 2023.09.02
2116 - 주사위 쌓기  (0) 2023.06.01
15654 - N과 M (5)  (0) 2023.01.23
2529 - 부등호  (0) 2023.01.17
2636 - 치즈  (0) 2023.01.12

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

 

15654번: N과 M (5)

N개의 자연수와 자연수 M이 주어졌을 때, 아래 조건을 만족하는 길이가 M인 수열을 모두 구하는 프로그램을 작성하시오. N개의 자연수는 모두 다른 수이다. N개의 자연수 중에서 M개를 고른 수열

www.acmicpc.net

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

int N, M;
vector<int> my_vector;
bool visited[10000 + 1];
int ans[10000 + 1];

void Run(const int start_idx, const int depth)
{
	if (visited[start_idx]) {
		return;
	}

	visited[start_idx] = true;
	ans[depth] = my_vector[start_idx];
	if (depth == M - 1) {
		for (int i = 0; i < M; i++) {
			cout << ans[i] << ' ';
		}

		cout << '\n';
		visited[start_idx] = false;
		return;
	}
	
	for (int i = 1; i < my_vector.size(); i++) {
		Run(i, depth + 1);
	}
	visited[start_idx] = false;
}

int main(void)
{
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);

	cin >> N >> M;
	my_vector.resize(N + 1);
	for (int i = 1; i <= N; i++) {
		cin >> my_vector[i];
	}

	sort(my_vector.begin(), my_vector.end());

	if (M == 1) {
		for (int i = 1; i <= N; i++) {
			cout << my_vector[i] << '\n';
		}

		return 0;
	}

	for (int i = 1; i <= N; i++) {
		Run(i, 0);
	}
}
  1. 재귀함수를 이용하여 풀 수 있는 문제였습니다.
  2. 지금 코드의 경우는 main 함수에서 Run을 N번 실행합니다.
  3. 하지만 이런 방식 말고, main 함수에서 Run 함수를 한 번만 실행하고 Run 내에서 여러번 호출하는 방식으로 코딩을 고쳐봐야 할 것 같습니다.

'문제풀이 > 백준' 카테고리의 다른 글

2116 - 주사위 쌓기  (0) 2023.06.01
12904 - A와 B  (0) 2023.05.21
2529 - 부등호  (0) 2023.01.17
2636 - 치즈  (0) 2023.01.12
2661 - 좋은 수열  (0) 2023.01.08

문제 :

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

 

2529번: 부등호

두 종류의 부등호 기호 ‘<’와 ‘>’가 k개 나열된 순서열 A가 있다. 우리는 이 부등호 기호 앞뒤에 서로 다른 한 자릿수 숫자를 넣어서 모든 부등호 관계를 만족시키려고 한다. 예를 들어, 제시

www.acmicpc.net

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

int K;
constexpr int MAX = 9;
constexpr int NUM_LENGTH_MAX = 10;
array<char, MAX + 1> inequality{ 0 };
array<int, NUM_LENGTH_MAX + 1> is_visited{ 0 };
vector<string> ans;

bool is_correct(string& temp)
{
	bool ret = true;
	for (int i = 0; i < K; i++) {
		if (inequality[i] == '<') {
			if (temp[i] >= temp[i + 1]) {
				return ret = false;
			}
		}
		else if (inequality[i] == '>') {
			if (temp[i] <= temp[i + 1]) {
				return ret = false;
			}
		}
	}

	return ret;
}

void Run(const int start_idx, const int depth, string temp)
{
	if (is_visited[start_idx]) {
		return;
	}

	is_visited[start_idx] = true;
	temp += to_string(start_idx);
	if (K == depth) {
		if (is_correct(temp)) {
			ans.push_back(temp);
		}

		is_visited[start_idx] = false;
		return;
	}

	for (int i = 0; i <= 9; i++) {
		Run(i, depth + 1, temp);
	}

	is_visited[start_idx] = false;
}

int main(void)
{
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	cin >> K;
	for (int i = 0; i < K; i++) {
		cin >> inequality[i];
	}

	for (int i = 0; i <= 9; i++) {
		Run(i, 0, "");
		memset(&is_visited, 0x00, sizeof(is_visited));
	}

	sort(ans.begin(), ans.end());

	cout << ans[ans.size() - 1] << '\n';
	cout << ans[0] << '\n';
	return 0;
}
  • 브루트포스 방법을 이용해 풀 수 있는 문제였습니다.
  • 재귀함수를 이용했습니다. 트리의 MAX 깊이가 10 이고, 모든 경우가 깊이 10까지 들어가지 않기 때문에 시간초과가 나지 않을 것이라고 생각했습니다.
  • 하지만 생각보다 elapsed time이 컸습니다. 방법을 수정해도 좋을것 같습니다.

'문제풀이 > 백준' 카테고리의 다른 글

12904 - A와 B  (0) 2023.05.21
15654 - N과 M (5)  (0) 2023.01.23
2636 - 치즈  (0) 2023.01.12
2661 - 좋은 수열  (0) 2023.01.08
2751 - 수 정렬하기 2  (0) 2023.01.06

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

 

2636번: 치즈

아래 <그림 1>과 같이 정사각형 칸들로 이루어진 사각형 모양의 판이 있고, 그 위에 얇은 치즈(회색으로 표시된 부분)가 놓여 있다. 판의 가장자리(<그림 1>에서 네모 칸에 X친 부분)에는 치즈가 놓

www.acmicpc.net

#include <iostream>
#include <queue>
#include <array>
#include <cstring>
using namespace std;

int col, row;
constexpr int MAX = 100 + 1;
int cheese_map[MAX][MAX];
bool is_visited[MAX][MAX];
const array<int, 4> dx = { -1, 1, 0, 0 };
const array<int, 4> dy = { 0, 0, -1, 1 };
int cnt = 0;
int final_cnt = 0;

namespace curr_state {
	const enum { CHEESE = 1, READY_MELTED, AIR };
}

void change_cheese_to_air()
{
	for (int i = 1; i <= row; i++) {
		for (int j = 1; j <= col; j++) {
			if (cheese_map[i][j] == curr_state::READY_MELTED) {
				cheese_map[i][j] = curr_state::AIR;
			}
		}
	}
}

void search_air()
{
	memset(is_visited, 0, sizeof(is_visited));

	queue<pair<int, int>> air_idx;
	air_idx.push({ 1,1 });
	while (!air_idx.empty()) {
		const int current_air_x_idx = air_idx.front().first;
		const int current_air_y_idx = air_idx.front().second;
		air_idx.pop();
		for (int i = 0; i < dx.size(); i++) {
			const int next_x = current_air_x_idx + dx[i];
			const int next_y = current_air_y_idx + dy[i];
			if (next_x < 1 || next_x > row || next_y < 1 || next_y > col) {
				continue;
			}

			if (is_visited[next_x][next_y]) {
				continue;
			}

			if (!cheese_map[next_x][next_y] || cheese_map[next_x][next_y] == curr_state::AIR) {
				air_idx.push({ next_x, next_y });
				cheese_map[next_x][next_y] = curr_state::AIR;
				is_visited[next_x][next_y] = true;
			}
		}
	}
}

void search_melted_cheese()
{
	memset(is_visited, 0, sizeof(is_visited));

	queue<pair<int, int>> to_be_melted_cheese;
	to_be_melted_cheese.push({ 1,1 });
	while (!to_be_melted_cheese.empty()) {
		const int current_air_x_idx = to_be_melted_cheese.front().first;
		const int current_air_y_idx = to_be_melted_cheese.front().second;
		to_be_melted_cheese.pop();
		for (int i = 0; i < dx.size(); i++) {
			const int next_x = current_air_x_idx + dx[i];
			const int next_y = current_air_y_idx + dy[i];
			if (next_x < 1 || next_x > row || next_y < 1 || next_y > col) {
				continue;
			}

			if (is_visited[next_x][next_y]) {
				continue;
			}

			if (curr_state::AIR == cheese_map[next_x][next_y]) {
				to_be_melted_cheese.push({ next_x, next_y });
				is_visited[next_x][next_y] = true;
			}

			if (cheese_map[current_air_x_idx][current_air_y_idx] == curr_state::AIR &&
				cheese_map[next_x][next_y] == curr_state::CHEESE) {
				cheese_map[next_x][next_y] = curr_state::READY_MELTED;
				to_be_melted_cheese.push({ next_x, next_y });
				is_visited[next_x][next_y] = true;
			}
		}
	}
}

bool is_clear_all()
{
	int remain_cnt = 0;
	for (int i = 1; i <= row; i++) {
		for (int j = 1; j <= col; j++) {
			if (curr_state::CHEESE == cheese_map[i][j]) {
				remain_cnt++;
			}
		}
	}

	if (remain_cnt) {
		final_cnt = remain_cnt;
		return false;
	}

	return true;
}

int main(void)
{
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);

	cin >> row >> col;
	for (int i = 1; i <= row; i++) {
		for (int j = 1; j <= col; j++) {
			cin >> cheese_map[i][j];
		}
	}

	int cnt = 0;
	while (!is_clear_all()) {
		cnt++;
		search_air();
		search_melted_cheese();
		change_cheese_to_air();
	}
	
	cout << cnt << '\n';
	cout << final_cnt << '\n';

	return 0;
}

** C++ 17 Clang으로 제출합니다. 그렇지 않으면 다음 구문에서 컴파일 에러가 발생합니다.

namespace curr_state {
	const enum { CHEESE = 1, READY_MELTED, AIR };
}

 

'문제풀이 > 백준' 카테고리의 다른 글

15654 - N과 M (5)  (0) 2023.01.23
2529 - 부등호  (0) 2023.01.17
2661 - 좋은 수열  (0) 2023.01.08
2751 - 수 정렬하기 2  (0) 2023.01.06
1920 - 수 찾기  (2) 2023.01.05

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

 

2661번: 좋은수열

첫 번째 줄에 1, 2, 3으로만 이루어져 있는 길이가 N인 좋은 수열들 중에서 가장 작은 수를 나타내는 수열만 출력한다. 수열을 이루는 1, 2, 3들 사이에는 빈칸을 두지 않는다.

www.acmicpc.net

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

int N;
string num;

void permutation(const char c, const int cnt)
{
    //조건 만족(제일 먼저 나오는 숫자가 제일 작은 수)

    if (cnt - 1 == N) {
        cout << num << "\n";
        exit(0);
    }

    num += c;

    for (int i = 1; i <= cnt / 2; i++) {
        const string&& a = num.substr(cnt - i, i);
        const string&& b = num.substr(cnt - i * 2, i);
        //나쁜 수열

        if (a == b) {
            num.erase(cnt - 1);
            return;
        }
    }

    for (int i = 1; i <= 3; i++) {
        permutation(i + '0', cnt + 1);
    }

    num.erase(cnt - 1);  //cnt - 1 자리가 성립하지 않을 경우
}

int main(void)
{
    cin >> N;
    for (int i = 1; i <= 3; i++) {
        permutation(i + '0', 1);
    }

    return 0;
}
 

재귀함수를 이용하여 풀 수있는 문제였습니다. 코드는 위 링크와 완전 동일합니다.

기본적으로 아래와 같은 방법으로 주어진 자리수의 숫자를 체크합니다.

  • 재귀함수를 이용하여 1 + 1 + 1 -> '111' 과 같은 방법으로 모든 숫자를 점검하는 컨셉입니다.
  • 하지만 실제로 모든 경우를 체크해볼 필요는 없습니다. 이유는 아래와 같습니다.
  • 1 + 1 + 1 이런식으로 체크하기 때문에, 가장 낮은수부터 체크하게끔 돼있습니다.
  • 그렇기 때문에, 만일 조건이 충족되는 최초의 숫자가 발견된다면, 그 즉시 프로그램 종료하면 됩니다. 그 숫자가 가장 작기 때문입니다.

위 사진과 같이 재귀함수를 이용해 각각의 case를 검사합니다.

 

'문제풀이 > 백준' 카테고리의 다른 글

2529 - 부등호  (0) 2023.01.17
2636 - 치즈  (0) 2023.01.12
2751 - 수 정렬하기 2  (0) 2023.01.06
1920 - 수 찾기  (2) 2023.01.05
5430 - AC  (0) 2023.01.05
#include <iostream>
#include <algorithm>
#include <array>
using namespace std;

int main(void)
{
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);

	int N;
	cin >> N;
	const int MAX_CNT = 1000000;
	array<int, MAX_CNT> my_arr;
	for (int i = 0; i < N; i++) {
		int num;
		cin >> num;
		my_arr[i] = num;
	}

	sort(my_arr.begin(), my_arr.begin() + N);

	for (int i = 0; i < N; i++) {
		cout << my_arr[i] << '\n';
	}

	return 0;
}

 

std sort를 이용하면 쉽게 풀 수 있는 문제였습니다.

'문제풀이 > 백준' 카테고리의 다른 글

2636 - 치즈  (0) 2023.01.12
2661 - 좋은 수열  (0) 2023.01.08
1920 - 수 찾기  (2) 2023.01.05
5430 - AC  (0) 2023.01.05
6603 - 로또  (0) 2023.01.03

+ Recent posts