solved.ac 기준 실버 1

 

1074번: Z

한수는 2차원 배열 (항상 2^N * 2^N 크기이다)을 Z모양으로 탐색하려고 한다. 예를 들어, 2*2배열을 왼쪽 위칸, 오른쪽 위칸, 왼쪽 아래칸, 오른쪽 아래칸 순서대로 방문하면 Z모양이다. 만약, 2차원 ��

www.acmicpc.net

<테스트 환경>

    C++

     - OS: Windows 10

     - IDE: JetBrains CLion

     - 컴파일러: MinGW GCC C++ compiler

    Python

     - OS: Windows 10

     - IDE: JetBrains PyCharm

     - 인터프리터: Python 3.8

 

답안 (C++ 14)

- 메모리: 1984 KB

- 시간: 0 ms

- boj.kr/c492da1533334445a952cf595eaed39c

#include <iostream>

int zeta_search(int n, int r, int c) {
    if (n == 1) {
        return r * 2 + c;
    } else if (n > 1) {
        return 4 * zeta_search(n - 1, r / 2, c / 2) + zeta_search(1, r % 2, c % 2);
    } else {
        return -1;
    }
}

int main() {
    int n, r, c;

    std::cin.tie(nullptr);
    std::ios::sync_with_stdio(false);

    std::cin >> n >> r >> c;
    std::cout << zeta_search(n, r, c) << '\n';

    return 0;
}

 

답안 (Python 3)

- 메모리: 29380 KB

- 시간: 60 ms

- boj.kr/c92231d4fe4f4ef0913c0d3fb661064c 

import sys


def zeta_search(n, r, c):
    if n == 1:
        return r * 2 + c
    elif n > 1:
        return 4 * zeta_search(n - 1, int(r / 2), int(c / 2)) + zeta_search(1, r % 2, c % 2)
    else:
        return -1


s = sys.stdin.readline()
n, r, c = map(int, s.split())

result = int(zeta_search(n, r, c))
print(result)

'기초쌓기 > PS' 카테고리의 다른 글

백준 10845번: 큐  (0) 2020.05.27
백준 10828번: 스택  (0) 2020.05.26
백준 1913번: 달팽이  (0) 2020.05.25
백준 1316번: 그룹 단어 체커  (0) 2020.05.25
백준 2750번: 수 정렬하기  (0) 2020.05.25

solved.ac 기준 실버 4

 

10845번: 큐

첫째 줄에 주어지는 명령의 수 N (1 ≤ N ≤ 10,000)이 주어진다. 둘째 줄부터 N개의 줄에는 명령이 하나씩 주어진다. 주어지는 정수는 1보다 크거나 같고, 100,000보다 작거나 같다. 문제에 나와있지 ��

www.acmicpc.net

큐(Queue)

큐(Queue)는 선입선출(first-in first-out, FIFO) 방식으로 자료형을 삽입하고 제거할 수 있는 자료구조이다. queue라는 단어는 "(무엇을 기다리는 사람들의) 줄" 이라는 의미도 있으므로, 흔히 표를 구입할 때 "먼저 줄 선 사람이 먼저 구입하고 빠지는 것" 비유하곤 한다.

버스는 먼저 줄 선 사람부터(first-in) 먼저 탄다(first-out)

 

구현해야 하는 명령 다섯가지

  • push X: 정수 X를 큐에 넣는 연산이다.
  • pop: 큐에서 가장 앞에 있는 정수를 빼고, 그 수를 출력한다. 만약 큐에 들어있는 정수가 없는 경우에는 -1을 출력한다.
  • size: 큐에 들어있는 정수의 개수를 출력한다.
  • empty: 큐가 비어있으면 1, 아니면 0을 출력한다.
  • front: 큐의 가장 앞에 있는 정수를 출력한다. 만약 큐에 들어있는 정수가 없는 경우에는 -1을 출력한다.
  • back: 큐의 가장 뒤에 있는 정수를 출력한다. 만약 큐에 들어있는 정수가 없는 경우에는 -1을 출력한다.

 

아이디어/참고

큐의 추상 자료형(ADT)은 다음과 같다. (출처: Data Structures & Algorithms in C++, 2nd Edition)

Algorithm size():
	return n
Algorithm empty():
	return (n = 0)
Algorithm front():
	if empty() then
		throw QueueEmpty exception
	return Q[f]
Algorithm dequeue():
	if empty() then
		throw QueueEmpty exception
	f←(f+1) mod N
	n = n−1
Algorithm enqueue(e):
	if size() = N then
		throw QueueFull exception
	Q[r]←e
	r←(r+1) mod N
	n = n+1

여기서 dequeue는 큐에서 자료를 제거하는 것이므로 pop에 대응, enqueue는 큐에 자료를 삽입하는 것이므로 push에 대응한다. 또한 가장 뒤에 있는 요소를 반환하는 back이 없으므로 이를 추가해주면 될 듯 하다.

front와 rear를 굳이 mod N으로 해주는 이유는, front나 back의 위치가 큐의 배열의 크기(N)를 넘어가면 안되므로 다시 처음으로 돌아가기 위함이다.

 

명령어 입력

이 문제 역시 명령어를 입력하여 정수만을 저장할 수 있으면 되는 것이므로, 명령어 입력에 대해 대략 수도코드를 짜보았다.

int n 선언
문자열 command 선언
Queue q 선언

n 입력받음
for i=0, i<n, i++
	cmd 입력받음
    if cmd = size then
    	q.size() 출력
    else if cmd = empty then
    	q.empty() 출력
    else if cmd = front then
    	q.front() 출력
    else if cmd = back then
    	q.front() 출력
    else if cmd = push then
    	int x 선언하고 입력받기
        q.push() 실행
    else if cmd = pop then
    	q.pop() 출력

 

테스트 환경

- OS: Windows 10

- IDE: Visual Studio Code

- 컴파일러: MinGW GCC C++ compiler

 

답안

- 메모리: 1172 KB

- 시간: 4 ms

- https://www.acmicpc.net/source/20047118

#include <stdio.h>
#include <string.h>

#define CAPACITY 5000

class CustomQueue {
    private:
        int n;
        int f, r;
        int capacity;
        int* queue_array;
    public:
        CustomQueue(int cap){
            n = 0;
            f = 0;
            r = 0;
            capacity = cap;
            queue_array = new int[cap];
        }
        int size(){
            return n;
        }
        int empty(){
            if (n == 0) return 1;
            else return 0;
        }
        int front(){
            if (n == 0) return -1;
            return queue_array[f];
        }
        int back(){
            if (n == 0) return -1;
            return queue_array[r-1];
        }
        void push(int x){
            queue_array[r] = x;
            r = (r+1) % capacity;
            n++;
        }
        int pop(){
            if (n == 0) return -1;
            int temp = queue_array[f];
            f = (f+1) % capacity;
            n--;
            return temp;
        }
};

int main()
{
    int n;
    char cmd[10];
    CustomQueue q(CAPACITY);

    scanf("%d", &n);
        for (int i=0; i<n; i++){
        scanf("%s", cmd);
        if (strcmp(cmd,"size") == 0){
            printf("%d\n", q.size());
        }
        else if (strcmp(cmd,"empty") == 0){
            printf("%d\n", q.empty());
        }
        else if (strcmp(cmd,"front") == 0){
            printf("%d\n", q.front());
        }
        else if (strcmp(cmd,"back") == 0){
            printf("%d\n", q.back());
        }
        else if (strcmp(cmd,"push") == 0){
            int x;
            scanf("%d", &x);
            q.push(x);
        }
        else if (strcmp(cmd,"pop") == 0){
            printf("%d\n", q.pop());
        }
    }

    return 0;
}

 

후기

스택에서 작성한 코드를 토대로 작성했더니 의외로 금방 풀 수 있었다. 그리고 자료구조에 대해 헷갈리는 게 많았는데 문제의 해결을 토대로 익히니까 머릿속에 남는 것이 많았다.

'기초쌓기 > PS' 카테고리의 다른 글

백준 1074번: Z (작성중)  (0) 2020.07.09
백준 10828번: 스택  (0) 2020.05.26
백준 1913번: 달팽이  (0) 2020.05.25
백준 1316번: 그룹 단어 체커  (0) 2020.05.25
백준 2750번: 수 정렬하기  (0) 2020.05.25

solved.ac 기준 실버 4

 

10828번: 스택

첫째 줄에 주어지는 명령의 수 N (1 ≤ N ≤ 10,000)이 주어진다. 둘째 줄부터 N개의 줄에는 명령이 하나씩 주어진다. 주어지는 정수는 1보다 크거나 같고, 100,000보다 작거나 같다. 문제에 나와있지 �

www.acmicpc.net

스택(Stack)

스택(Stack)은 후입선출(Last-in first-out, LIFO) 방식으로 자료를 삽입하거나 제거할 수 있는 자료구조 중 하나이다.

이번 문제는 이 스택을 구현하고 이를 명령어로 실행하는 것을 요구한다.

출처: 위키백과

 

구현해야 하는 명령 다섯가지

  • push X: 정수 X를 스택에 넣는 연산이다.
  • pop: 스택에서 가장 위에 있는 정수를 빼고, 그 수를 출력한다. 만약 스택에 들어있는 정수가 없는 경우에는 -1을 출력한다.
  • size: 스택에 들어있는 정수의 개수를 출력한다.
  • empty: 스택이 비어있으면 1, 아니면 0을 출력한다.
  • top: 스택의 가장 위에 있는 정수를 출력한다. 만약 스택에 들어있는 정수가 없는 경우에는 -1을 출력한다.

아이디어/참고

스택의 추상 자료형(ADT)은 다음과 같다. (출처: Data Structures & Algorithms in C++, 2nd Edition)

Algorithm size():
	return t+1
Algorithm empty():
	return (t<0)
Algorithm top():
	if empty() then
		throw StackEmpty exception
	return S[t]
Algorithm push(e):
	if size() = N then
		throw StackFull exception
	t←t+1
	S[t]←e
Algorithm pop():
	if empty() then
		throw StackEmpty exception
	t←t−1

이를 클래스로 만들면 될 것 같다. 그리고 해당 문제는 정수만 구현하면 된다.

 

명령어 입력

이 문제는 단순 스택의 함수를 호출하는 것이 아닌 명령어가 입력으로 주어지면 호출하는 방식이므로, 명령어를 받아들이고 조건문을 통하여 명령어가 맞으면 해당 명령을 실행하는 식으로 코드를 짜면 될 것 같다.

int n 선언
string command 선언
Stack s 선언
n 입력받음

for i=0, i<n, i++
	cmd 입력받음
    if cmd = size then
    	s.size() 출력
    else if cmd = empty then
    	s.empty() 출력
    else if cmd = top then
    	s.top() 출력
    else if cmd = push then
    	int x 선언하고 입력받기
        s.push() 실행
    else if cmd = pop then
    	s.pop() 출력

테스트 환경

- OS: Windows 10

- IDE: Visual Studio Code

- 컴파일러: GCC

 

첫 번째 답안

- 코드 용량: 1988KB

- 실행 시간: 312ms

- https://www.acmicpc.net/source/20033960

#include <iostream>
#include <string>

using namespace std;

#define CAPACITY 1000

class CustomStack {
    private:
        int* stack_array;
        int capacity;
        int t;
    public:
        CustomStack(int cap){
            stack_array = new int[cap];
            capacity = cap;
            t = -1;
        }
        int size() const{
            return (t+1);
        }
        int empty() const{
            if (t<0)
                return 1;
            else
                return 0;
        }
        int top() const{
            if (empty() == 1) return -1;
            return stack_array[t];
        }
        void push(int x){
            t++;
            stack_array[t] = x;
        }
        int pop(){
            if (empty() == 1) return -1;
            int temp = stack_array[t];
            t--;
            return temp;
        }
};

int main()
{
    int n;
    string cmd;
    CustomStack s(CAPACITY);

    cin >> n;
    for (int i=0; i<n; i++){
        cin >> cmd;
        if (cmd == "size"){
            cout << s.size() << '\n';
        }
        else if (cmd == "empty"){
            cout << s.empty() << '\n';
        }
        else if (cmd == "top"){
            cout << s.top() << '\n';
        }
        else if (cmd == "push"){
            int x;
            cin >> x;
            s.push(x);
        }
        else if (cmd == "pop"){
            cout << s.pop() << '\n';
        }
    }

    return 0;
}

두 번째 답안

- 문제를 풀다보니 실행시간이 312ms나 나올 게 있나..? 하는 생각이 들어서 찾아봤더니, std::cin과 std::cout이 printf와 scanf보다 속도가 엄청 느리다는 이야기가 있었다. 다른 사람들이 C++로 작성한 것을 참고해보니 전부 printf와 scanf를 사용하였다.

- 참고: https://algospot.com/forum/read/2496/

std::cin은 sync_with_stdio를 사용하지 않으면 scanf와 비교하여 수행시간이 큰 차이가 난다.

 

- 코드 용량: 1172KB

- 실행 시간: 4ms

- https://www.acmicpc.net/source/20034694

#include <stdio.h>
#include <string.h>

#define CAPACITY 1000

class CustomStack {
    private:
        int* stack_array;
        int capacity;
        int t;
    public:
        CustomStack(int cap){
            stack_array = new int[cap];
            capacity = cap;
            t = -1;
        }
        int size() const{
            return (t+1);
        }
        int empty() const{
            if (t<0)
                return 1;
            else
                return 0;
        }
        int top() const{
            if (empty() == 1) return -1;
            return stack_array[t];
        }
        void push(int x){
            t++;
            stack_array[t] = x;
        }
        int pop(){
            if (empty() == 1) return -1;
            int temp = stack_array[t];
            t--;
            return temp;
        }
};

int main()
{
    int n;
    char cmd[10];
    CustomStack s(CAPACITY);

    scanf("%d", &n);
    for (int i=0; i<n; i++){
        scanf("%s", cmd);
        if (strcmp(cmd,"size") == 0){
            printf("%d\n", s.size());
        }
        else if (strcmp(cmd,"empty") == 0){
            printf("%d\n", s.empty());
        }
        else if (strcmp(cmd,"top") == 0){
            printf("%d\n", s.top());
        }
        else if (strcmp(cmd,"push") == 0){
            int x;
            scanf("%d", &x);
            s.push(x);
        }
        else if (strcmp(cmd,"pop") == 0){
            printf("%d\n", s.pop());
        }
    }
    return 0;
}

std::cin과 std::cout을 printf와 scanf로 바꾸었더니 312ms -> 4ms로 확연히 차이가 난다.

'기초쌓기 > PS' 카테고리의 다른 글

백준 1074번: Z (작성중)  (0) 2020.07.09
백준 10845번: 큐  (0) 2020.05.27
백준 1913번: 달팽이  (0) 2020.05.25
백준 1316번: 그룹 단어 체커  (0) 2020.05.25
백준 2750번: 수 정렬하기  (0) 2020.05.25

solved.ac 기준 실버 5

 

1913번: 달팽이

N개의 줄에 걸쳐 표를 출력한다. 각 줄에 N개의 자연수를 한 칸씩 띄어서 출력하면 되며, 자릿수를 맞출 필요가 없다. N+1번째 줄에는 입력받은 자연수의 좌표를 나타내는 두 정수를 한 칸 띄어서

www.acmicpc.net

아이디어/참고

https://codepractice.tistory.com/81 해당 페이지에 있는 사진을 참고하였다.

 (0, 0) 좌표에서 입력받은 값 n의 2승(=n^2) 부터 시작하여 행(row)의 값이 증가하는 방향으로 시작

 

테스트 환경

- OS: Windows 10

- IDE: Visual Studio Code

- 컴파일러: Visual C++

 

첫 번째 답

- 코드 용량: 1988KB

- 실행 시간: 156ms

- 아이디어

실행 순서

- 답안

#include <iostream>

using namespace std;

void snail(int n, int find)
{
    int l = n;
    int value = n * n;
    int row = -1;
    int col = 0;
    int dir = 1;
    int x, y;
    int** arr;
    arr = new int* [n];
    for(int i=0; i<n; i++) arr[i] = new int[n];

    while (l > 0){
        for (int i=0; i<l; i++){
            row = row + dir;
            arr[row][col] = value;
            if (value == find){
                x = col + 1;
                y = row + 1;
            }
            value--;
        }
        l--;
        for (int i=0; i<l; i++){
            col = col + dir;
            arr[row][col] = value;
            if (value == find){
                x = col + 1;
                y = row + 1;
            }
            value--;
        }
        dir = dir * (-1);
    }

    for(int i=0; i<n * n; i++){
        int r = i / n;
        int c = i % n;
        cout << arr[r][c] << " ";
        if((i % n) == n - 1) cout << endl;
    }

    cout << y << " " << x << endl;
    
    for(int i=0; i<n; i++) delete[] arr[i];
    delete[] arr;
}

int main()
{
    int n, find;
    cin >> n >> find;
    snail(n, find);
    return 0;
}

 

두 번째 답

첫 번째 코드의 경우 아이디어를 따왔던 게시글에 있는 코드와 유사하게 짰음.

이번엔 꼭지점에 도달할 경우 방향을 바꾸는 방식으로 진행.

- 코드 용량: 1988KB

- 실행 시간: 156ms

- 아이디어

첫 열에 대해 값 입력.
꼭지점에 도달하고, 두 번째 열이 첫번째가 되도록 함.
꼭지점에 도달하고, 네 번째 행이 마지막이 되도록 함.

 

 

 

 

 

 

 

 

 

 

 

 

- 답안

#include <iostream>

using namespace std;

void snail(int n, int find)
{
    int row = 0, col = 0;
    int value = n*n;
    int rfirst = 0, cfirst = 0;
    int rlast = n-1, clast = n-1;
    int x, y;
    int** arr;
    arr = new int* [n];
    for(int i=0; i<n; i++) arr[i] = new int[n];

    while (value > 0){
        arr[row][col] = value;
        if (value == find){
            x = col + 1;
            y = row + 1;
        }
        value--;
        if (row < rlast && col == cfirst){
            row++;
            if (row == rlast) cfirst++;
        }
        else if (row == rlast && col < clast){
            col++;
            if (col == clast) rlast--;
        }
        else if (row > rfirst && col == clast){
            row--;
            if (row == rfirst) clast--;
        }
        else if (row == rfirst && col > cfirst){
            col--;
            if (col == cfirst) rfirst++;
        }
    }
    
    for(int i=0; i<n * n; i++){
        int r = i / n;
        int c = i % n;
        cout << arr[r][c] << " ";
        if((i % n) == n - 1) cout << endl;
    }

    cout << y << " " << x << endl;
    
    for(int i=0; i<n; i++) delete[] arr[i];
    delete[] arr;
}

int main()
{
    int n, find;
    cin >> n >> find;
    snail(n, find);
    return 0;
}

 

'기초쌓기 > PS' 카테고리의 다른 글

백준 1074번: Z (작성중)  (0) 2020.07.09
백준 10845번: 큐  (0) 2020.05.27
백준 10828번: 스택  (0) 2020.05.26
백준 1316번: 그룹 단어 체커  (0) 2020.05.25
백준 2750번: 수 정렬하기  (0) 2020.05.25

- 문제 주소: https://www.acmicpc.net/problem/1316

- solved.ac 기준 실버 5

 

1316번: 그룹 단어 체커

그룹 단어란 단어에 존재하는 모든 문자에 대해서, 각 문자가 연속해서 나타나는 경우만을 말한다. 예를 들면, ccazzzzbb는 c, a, z, b가 모두 연속해서 나타나고, kin도 k, i, n이 연속해서 나타나기 때�

www.acmicpc.net

문제풀이 초안

- 제출한 답: C++로 작성, 1988KB

- 결과: 정답

#include <string>
#include <iostream>

using namespace std;

bool isGroupWord(string str) {
	int i = 0;
	while (i < str.length() - 1) {
    	// 인접한 두 문자가 같은 문자일 경우 스킵
		if (str.at(i) == str.at(i + 1)) {
			i++;
		} else {
			for (int j = i + 1; j < str.length(); j++) {
            	// 연속해서 나타나지 않는 경우 false 반환
				if (str.at(i) == str.at(j))
					return false;
			}
			i++;
		}
	}
	return true;
}

int main() {
	int n, count;
	string* str;

	// 단어 개수 입력받고 str에 배열 동적할당
	cin >> n;
	str = new string[n];

	// 단어 입력
	for (int i = 0; i < n; i++) {
		cin >> str[i];
	}
	
	count = 0;
	
    // 단어가 그룹 단어이면 count를 1 증가시킴
	for (int i = 0; i < n; i++) {
		if (isGroupWord(str[i])) count++;
	}

	cout << count << endl;
    
	delete[] str;
	return 0;
}

시간복잡도를 최적화한 풀이

- 이미 등장한 알파벳인지를 판단하는 불 타입 배열 선언

- 제출한 답: C++로 작성, 1988KB

- 결과: 정답

#include <string>
#include <iostream>

using namespace std;
const char LITTLE_A = 'a';

bool isGroupWord(string str) {
	// 단어 중복을 체크할 불 배열 선언
	bool* wordCheck = new bool[26]{ false, };
	wordCheck[str.at(0) - LITTLE_A] = true;
	for (int i = 1; i < str.length(); i++) {
		// 이미 등장한 알파벳인지 체크 
		if (!wordCheck[str.at(i) - LITTLE_A])
			wordCheck[str.at(i) - LITTLE_A] = true;
		// 만약 이미 등장한 알파벳이라면 앞자리의 알파벳과 동일한지 체크
		else
			if (str.at(i) != str.at(i - 1)) return false;
	}
	delete[] wordCheck;
	return true;
}

int main() {
	int n, count;
	string* str;

	// 단어 개수 입력받고 str에 배열 동적할당
	cin >> n;
	str = new string[n];

	// 단어 입력
	for (int i = 0; i < n; i++) {
		cin >> str[i];
	}

	count = 0;

	// 단어가 그룹 단어이면 count를 1 증가시킴
	for (int i = 0; i < n; i++) {
		if (isGroupWord(str[i])) count++;
	}

	cout << count << endl;

	delete[] str;

	return 0;
}

'기초쌓기 > PS' 카테고리의 다른 글

백준 1074번: Z (작성중)  (0) 2020.07.09
백준 10845번: 큐  (0) 2020.05.27
백준 10828번: 스택  (0) 2020.05.26
백준 1913번: 달팽이  (0) 2020.05.25
백준 2750번: 수 정렬하기  (0) 2020.05.25

- 문제 주소: https://www.acmicpc.net/problem/2750

- solved.ac 기준 실버 5

 

2750번: 수 정렬하기

첫째 줄에 수의 개수 N(1 ≤ N ≤ 1,000)이 주어진다. 둘째 줄부터 N개의 줄에는 숫자가 주어진다. 이 수는 절댓값이 1,000보다 작거나 같은 정수이다. 수는 중복되지 않는다.

www.acmicpc.net

 

[5월 24일]

- 제출한 답: C++로 작성, 1984KB

- 선택 정렬 (https://ko.wikipedia.org/wiki/%EC%84%A0%ED%83%9D_%EC%A0%95%EB%A0%AC) 이용

- 결과: 정답, 시간 36ms

#include <iostream>

using namespace std;

void swap(int &a, int &b) {
	int temp;
	temp = a;
	a = b;
	b = temp;
}

void sort(int *arr, int n) {
	int min;
	for (int i = 0; i < n - 1; i++) {
		min = i;
		for (int j = i; j < n; j++) {
			if (arr[j] < arr[min]) {
				min = j;
			}
		};
		swap(arr[i], arr[min]);
	}
}

int main() {
	int n, *arr;
	cin >> n;
	arr = new int[n];
	for (int i = 0; i < n; i++) {
		cin >> arr[i];
	}
	sort(arr, n);
	for (int i = 0; i < n; i++) {
		cout << arr[i] << endl;
	}
	delete[] arr;
	return 0;
}

 

'기초쌓기 > PS' 카테고리의 다른 글

백준 1074번: Z (작성중)  (0) 2020.07.09
백준 10845번: 큐  (0) 2020.05.27
백준 10828번: 스택  (0) 2020.05.26
백준 1913번: 달팽이  (0) 2020.05.25
백준 1316번: 그룹 단어 체커  (0) 2020.05.25

+ Recent posts