문제출처 : https://www.acmicpc.net/problem/1182


1. 문제요약

- 집합, N개의 원소, 부분집합의 합이 S를 만족시키는 경우의 수

- N < 20, lSl < 1,000,000, l원소l < 100,000

- 공집합은 제외


2. 접근방법

- 부분집합의 개수는 2^N = 2^20 ≒ 1억번 ≒ 1초

- 모든 부분집합의 합을 다 구해보면 된다.


3. 시간복잡도

- 재귀 : 2^N => 테스트 결과 4ms

- Bit Mask : 2^N * N => 테스트 결과 52ms


4. 회고

- 재귀로 구현했을 때

  : 공집합인지 확인하는 과정이 필요함. S의 값이 0인 경우 공집합의 합은 0 이므로

  : 처음에는 선택한 원소의 개수도 재귀로 넘겼는데 S가 0이 아닌 경우는 공집합을 포함해도 경우의 수에 포함 되지 않으므로 

   마지막에 계산할 때, S가 0인 경우 1가지 경우의 수를 빼주면 됨.


- Bit Mask로 구현했을 때

  : 좀 더 구현에 연습이 필요함



재귀 소스코드


Bit Mask 소스코드



[출처 : BOJ, 문제에 대한 모든 권리는 BOJ(acmicpc.net, startlink)에 있음]

'먹고살려면 > boj' 카테고리의 다른 글

BOJ 1966 프린터 큐  (0) 2017.12.26
BOJ 7568 덩치  (0) 2017.12.19
BOJ 6603 로또  (0) 2017.12.19
BOJ 2309 일곱난쟁이  (0) 2017.12.13
BOJ 1065 한수  (0) 2017.12.12

문제출처 : https://www.acmicpc.net/problem/2309


1. 문제요약

- 9명의 난쟁이 중 키의 합이 100이 되는 7명의 난쟁이를 뽑아 오름차순으로 출력


2. 접근방법

- 단순하게 9명 중 7명을 뽑아서 키의 합이 100이 되면 출력 후 종료 => 조합 9C7

- 9C7 = 9C2 이므로 9명의 총 합에서 100을 제외한 값을 만족하는 2명만 뽑아서 나머지를 출력


3. 시간복잡도

- 9C7 재귀 구현의 경우 O(2^N) = 2^9

- 9C2 for 구현의 경우 O(NC2) = 9C2 => for를 계산해보면 8 + 7 + 6 + 5 + ... + 2 + 1 = 36


4. 회고

- 9C7을 재귀로 구현했을 때

  재귀에서 '정답인 경우'와 '정답이 아닌 경우'를 잘못 선정해서 무한루프에...

  base case를 잘 생각해보자

- 조합을 재귀 말고 쉽게 구현할 수 있는 방법이 있을까? 아직 지하 밑바닥에 있어서 좀 더 경험이 필요할 듯


- 9C2를 for로 구현했을 때 sort에서 a+10을 해버렸....왜 0이 나오나 했네



소스코드 : 9C2




[출처 : BOJ, 문제에 대한 모든 권리는 BOJ(acmicpc.net, startlink)에 있음]

'먹고살려면 > boj' 카테고리의 다른 글

BOJ 1966 프린터 큐  (0) 2017.12.26
BOJ 7568 덩치  (0) 2017.12.19
BOJ 6603 로또  (0) 2017.12.19
BOJ 1182 부분집합의 합  (0) 2017.12.16
BOJ 1065 한수  (0) 2017.12.12

오늘도 여전히 줍줍


std::ios::sync_with_stdio(false)


cout << ... << "\n";


http://gooddaytocode.blogspot.kr/2016/07/cin-scanf.html


https://algospot.com/forum/read/2496/


https://www.acmicpc.net/board/view/20309

문제출처 : https://www.acmicpc.net/problem/1065


1. 문제요약

- 입력이 N일 때, 각 자릿수의 차이가 같은 수(한수)의 개수는?


※ 한 자릿수와 두 자릿수의 경우 어떻게 처리되나 했더니

예제에


입력 : 110

출력 : 99


즉, 2자리수 까지는 모두 등차수열로 판단 == 한수


2. 접근방법

n <= 1000보다 작은 자연수 이므로 세 자릿수만 한수인지 확인하면 된다.


3. 시간복잡도

- 두 자릿수 입력만 받는다면 O(1)이겠지만, 3자릿수가 넘어가면 각각의 수에 대해 확인해야하므로 O(N)


1) 각 자릿수의 차를 직접 구해보기

- 세 번째 자릿수 - 두 번째 자릿수 == 두 번째 자릿수 - 첫 번째 자릿수


소스코드



2) 등차수열의 특징을 활용

- 사실 특징이라고 할게 있나...

- a, a+d, a+2d ... 이므로 a + a+2d = (a+d) * 2


소스코드



[출처 : BOJ, 문제에 대한 모든 권리는 BOJ(acmicpc.net, startlink)에 있음]

'먹고살려면 > boj' 카테고리의 다른 글

BOJ 1966 프린터 큐  (0) 2017.12.26
BOJ 7568 덩치  (0) 2017.12.19
BOJ 6603 로또  (0) 2017.12.19
BOJ 1182 부분집합의 합  (0) 2017.12.16
BOJ 2309 일곱난쟁이  (0) 2017.12.13

1. 무식하게 풀기(brute-force)

- 가장 많이 하는 실수 중 하나가 쉬운 문제를 어렵게 푸는 것

- 공부를 열심히 할수록 복잡하지만 우아한 답안에 집착하기에..

- 부르트포스 문제는 빠르면서도 정확한 구현능력을 요구함

- 부르트포스는 더 빠른 알고리즘의 근간이 되기에 잘 익혀둘 필요가 있음



2. 재귀 호출과 완전 탐색

1) 재귀 호출

※ tail recursion 이라는 것도 있긴하지만 여기서 설명은 하지 않음

- 큰 조각을 반복되는 유사한 작은 조각들로 나누어 접근하는 것

- 작은 조각들 중 하나를 자신이 해결하고 나머지 조각들을 자기 자신을 호출해서 해결


예) 1 ~ n까지 합

int recursum(int n){
	if(n == 1) return 1;
	return n + recursum(n-1);
}

  n 과 1 ~ n-1 까지의 합으로 구분 => n-1과 1~ n-2 까지의 합으로 다시 구분 ... => 2와 1 ~ 1 까지의 합으로 마지막 구분

  n 의 합을 스스로 처리하고 나머지 1 ~ n-1 까지의 합을 자기자신을 호출하여 처리함


- 재귀는 크게 두 부분으로 구성됨

  base case : 더이상 쪼개지지 않는 작업, 최소 입력에 대한 작업, 답이 없을 경우에 대한 작업

  general case : base case를 제외한 재귀를 호출할 작업



예제. 문제 : PICNIC

- 절차적 접근

https://algospot.com/judge/problem/read/PICNIC


1) 문제를 읽고 이해하기

  : 시간제한 1000ms

  : 메모리제한 2^16kb

  : 2 <= n <= 10


2) 문제 재정의

  : 서로 친구인 학생 끼리 짝을 짓는 경우의 수


3) 계획 세우기

  : 짝이 지어지지 않은 학생을 골라서 친구사이인 다른 학생과 짝을 지어줌

  : 아직 짝이 지어지지 않은 학생을 대상으로 위 과정을 반복

  => "한쌍" 과 "짝이 지어지지 않은 학생" 으로 문제를 분할 => 재귀


4) 계획 검증하기

  : 시간복잡도 : 첫 짝이 없는 친구를 고르는 경우(1)(0 학생이 무조건 처음이므로) * 0학생과 친구인 관계(N-1) * 0과 0 친구를 제외한 다음 짝이 없는 친구를 고르는 경우(N-2) * 두 번째 고른 학생과 친구인 관계(N-3) * ... * 1 = 9! ≒ 360,000 

   즉, 1억번 내에 들어옴

  : 공간복잡도 : global variable - int * 3 = 12byte

                    local variable - bool * 100 + bool * 10 = 110byte

                    ≒ 122byte

   즉, 2^16kb 이내


5, 6) 계획 수행하기 및 회고하기


실패한 소스코드

- 중복처리를 안해줌

- 해당 코드에서는 (0, 1) (2, 3) 과 (2, 3) (0, 1) 이 다른 경우로 판단함.



성공한 소스코드

- 중복처리는 시작점을 고정하는게 제일 좋음

- 단, 이 방법은 a와 b가 친구이면 isfriend[a][b] = isfriend[b][a] = true로 해줘야 (1,2) (3,0) 같은 경우를 골라낼 수 있음

- 아니면 0과 3이 친구가 아니므로 경우의 수가 빠지게 됨


※ 시간복잡도 : 학생 하나 고르는데 걸리는 시간(1) * 고른 학생과 친구인 학생 고르는데 걸리는 시간(N-1) * 두명을 제외한 학생 한명과 그 친구를 고르는데 걸리는 시간(N-3) * ... * 1= 9 * 7 * 5 * 3 * 1 = 945

   공간복잡도 : 위 공간복잡도 + 각 재귀마다 int student가 추가됨(int * (9 * 7 * 5 * 3 * 1) = 3780byte

   즉, 3920byte




※ 왜 종만북의 코드와 속도는 동일하지만 종만북 코드로 제출한 사람들의 코드는 0ms도 있음

   무슨 차이일까 코드를 보았더니

   눈에 띄는 차이는 cin, cout과 scanf, printf

   나중에 입출력 속도에 대해 정리된거 줍줍해와야겠음



- 알고리즘 문제 해결전략 1편 중 -

- 저작권 문제시 삭제하겠습니다 -

1. 왜 필요한가

- 알고리즘의 수행 속도를 대략적으로 측정하기 위해서

- A 알고리즘이 B 알고리즘 보다 빠르다 느리다 얼마만에 수행이 된다 등


※ 왜 프로그램 수행 속도가 아닌 알고리즘의 수행 속도를 사용하는가?

- 프로그램 수행 속도는 하드웨어, OS, 컴파일러, 언어 등에 따라 바뀔 수 있기 때문

- 위의 외적인 이유를 같게 하더라도 어떤 STL을 썼는가, 파라미터, 반복문 내 수행되는 명령문의 개수 등에 따라도 바뀔 수 있기 때문

- 프로그램 수행 속도는 다양한 입력에 대한 실행 시간을 반영하지 못함(입력이 커지면 수행 속도도 달라지기 때문)



2. 속도 측정 기준

- 반복문이 돌아가는 횟수를 기준으로 함

※ 반복문을 제외한 나머지는?

- 입력의 크기가 충분히 크다면 반복문을 제외한 나머지 명령문의 수행 횟수는 전체 명령문의 수행 횟수에서 비율이 점점 줄어들 것이기 때문

 

- 입력의 크기에 따라 알고리즘 내 반복문의 수행 횟수가 달라지기 때문에 "입력의 크기에 대한 함수"로 표현 =>시간 복잡도 표현의 시작



3. 알고리즘 "시간 복잡도"의 표현과 예제

- Big-O Notation

※구술로 말할때는 Order 라고도 함

- Big-Ω

- Big-Θ


- Big-O 계산 방법 : 가장 큰 항만 남김, 상수 제외

※ 단, 알고리즘 문제를 풀면서 상수가 중요한 경우도 있으니 복잡하지 않으면 상수도 포함하여 계산하는 것도 나쁘지 않음


- 예제 : selection sort, insertion sort

1) selection sort

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

void selectionSort(vector<int>& arr){
	for (int i = 0; i < (int)arr.size(); i++){
		int minIndex = i;

		for (int j = i; j < (int)arr.size(); j++){
			if (arr.at(minIndex) > arr.at(j))
				minIndex = j;
		}

		swap(arr[i], arr[minIndex]);
	}
}

int main(void){
	vector<int> a(10, 0);
	
	for (int i = 0; i < (int)a.size(); i++)
		a[i] = (rand() % 10);

	for (int i = 0; i < (int)a.size(); i++)
		cout << a.at(i) << " ";
	cout << "\n";

	selectionSort(a);
	for (int i = 0; i < (int)a.size(); i++)
		cout << a.at(i) << " ";
	cout << "\n";
	return 0;
}

<src 1 : selection sort>

  : (N-1) + (N-2) + ... + 1 = ½N(N-1) = ½N^2 - ½N => O(N^2)


2) insertion sort

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

void insertionSort(vector<int>& arr){
	for (int i = 0; i < (int)arr.size(); i++){
		int j = i;
		while (j > 0 && arr[j] < arr[j-1]){
			swap(arr[j], arr[i]);
			j--;
		}
	}
}

int main(void){
	vector<int> a(10, 0);
	
	for (int i = 0; i < (int)a.size(); i++)
		a[i] = (rand() % 10);

	for (int i = 0; i < (int)a.size(); i++)
		cout << a.at(i) << " ";
	cout << "\n";

	insertionSort(a);
	for (int i = 0; i < (int)a.size(); i++)
		cout << a.at(i) << " ";
	cout << "\n";

	return 0;
}

<src 2 : insertion sort>

  : 1 + 2 + ... + N-2 + N-1 => O(N^2)



4. 시간 복잡도 어림짐작

- 대충 때려 맞추기(개인적으로 가장 많이 이용하는 방법) => 반복의 횟수가 약 1억번(2^20, 10!) 이면 1초에 실행 된다고 판단

  (단, 반복문 안이 길면 그보다 더 걸리고 짧으면 그보다 더 적게 걸림)

  : 1개가 끝나는데 걸리는 시간 * 총 개수

  : selection sort에서 1개가 정렬되려면 최악 N * 총 배열 개수가 N = N^2

  : insertion sort에서 1개가 정렬되려면 최악 N * 총 배열 개수가 N = N^2

  : Map에서 중복되지 않고 모든 칸을 가는 경우 = N^2

  : 선택 하고 안하고의 문제 = 2^N (선택의 경우가 3, 4... 이라면 3^N, 4^N 즉, 경우의 수)


                      (fig 1)

- fig 1 에 있는건 연산 결과 1억번이 나오는 N의 입력 크기

  ex) 1만^2 = 1억



공간복잡도 분석


- 알고리즘 문제 해결전략 1편 중 -

- 저작권 문제시 삭제하겠습니다 -

'먹고살려면 > Algorithm' 카테고리의 다른 글

3-2편 무식하게 풀기 2  (0) 2017.12.18
번외편 c/c++ 입력속도  (0) 2017.12.12
3-1편 무식하게 풀기 1  (0) 2017.12.11
1편 알고리즘 문제 풀이를 위한 전략  (0) 2017.12.01
알고리즘 시작하기  (0) 2017.11.30

1. 2진수


1.1 2진수와 16진수

- 변환 : 16진수는 십진수로 0~15까지 표현이 가능하다. 이진수로는 0000~1111까지 표현이 가능하다.

          2진수에서 16진수로 변환은 오른쪽부터 4bit씩 잘라서 변환하면 된다.

          1110001(2) =>  111(2) = 2^3 - 1 = 7

                              0001(2) = 1

          1110001(2) = 71(16)



1.2 용어

- word : 사용하는 프로세서가 몇 비트냐에 따라 워드의 크기가 바뀐다.

           한번에 처리할 수 있는 단위(일반적으로 레지스터의 크기라고 보며된다.)

           32bit processor라면 32bit = 1word

※ 현재 공부하고 있는 프로세서가 몇 비트인지 알아둬야 한다.

   (단, 32bit 임에도 SW상에서는 16bit를 1word로 처리하는 프로세서가 있다.)

   (이유는 나중에... 나에게 별로 중요하지 않은 부분이라 앞으로 설명할 기회가 있을지는 모르겠다.)


- MSB(Most Significant Bit), LSB(Least SIgnificant Bit)

  MSB : 최상위 비트

  LSB : 최하위 비트

  101100(2) 에서  

    1        0 1 1 0        0

  MSB                     LSB



1.3 2진수의 표현

- Signed-Magnitude

- One's Complement

- Two's Complement

- 앞으로는 2의 보수만 사용할 것이다. 1의 보수나 부호와 크기 표현은 대표적으로 0이 두개인 문제가 발생함.(다른 문제도 있음)

(설명은 귀찮으니 패스...)

- 2의 보수에서 표현 범위 : [-2^(N-1) ~ 2^(N-1)-1] (참고로 '[ ]'는 닫힌구간)



1.4 Overflow / Underflow

- Overflow : 절대값의 표현범위가 자료형이 나타낼 수 있는 범위를 넘어설 때

  17.12.19 추가 : 코딩시 signed인지 unsigned인지 확인이 중요

  c++에서 벡터 v.size() - 1 은 overflow를 일으킬 수 있음. v.size()는 unsigned int 형으로 만약 벡터 크기가 0일 경우

  0 - 1은 4,294,967,295(1111 1111 | 1111 1111 | 1111 1111 | 1111 1111, 32bit) 가 나옴

  (위와 같은 경우를 underflow라고 하는건 잘못된 표현, underflow는 엄연히 다른 표현임)

  overflow를 피하려면 1. (explicit) type casting  

                             2. v.size() - 1 표현을 안쓰는 것


- Underflow : 부동소수점 표현방식에서 지수부가 타입의 한계를 넘어 작아지면 0에 가까워 지는 것

(난 잘 주워오니까 그림으로 때우겠다)

출처는 아래에 있습니다.

- 2의 보수 표현(signed)에서 양수 + 음수의 덧셈은 오버플로우를 일으키지 않음

- 음수 + 음수의 크기가 -2^(N-1)보다 작거나 양수 + 양수의 크기가 2^(N-1) - 1 보다 큰 경우를 오버플로우

  즉, 캐리의 여부와 관계없이 앞의 부호가 바뀌는 경우가 오버플로우(단, 2의 보수 표현에서만)



1.5 sign-extention

- MSB를 계속 늘리면 됨

- 3  = 0011(2) = 0000 0011(2)

- -3 = 1101(2) = 1111 1101(2)



-출처

http://slideplayer.com/slide/5946574/

https://courses.cs.washington.edu/courses/cse370/98sp/lectures/04-combex/sld026.htm

http://slideplayer.com/slide/9942560/

https://namu.wiki/w/%EC%98%A4%EB%B2%84%ED%94%8C%EB%A1%9C

https://stackoverflow.com/questions/6360049/what-are-arithmetic-underflow-and-overflow-in-c



2. 논리 게이트


2.1 논리 게이트

- 하나 또는 그 이상의 2진수 입력을 받아서 하나의 출력을 만들어 내는 간단한 디지털 회로



2.2 논리 게이트 종류

※ 논리게이트의 심벌과 진리표는 구글 검색

  1) NOT

  2) BUF : 버퍼 : 논리적 관점 - 데이터의 전달

                      아날로그적 관점 - 많은 양의 전류를 공급, 하나의 입력을 다른 많은 게이트에게 전달, 데이터 복원

  3) AND

  4) OR

  5) XOR

  6) NAND

  7) NOR

  8) XNOR


- N input gate : 2개씩 나눠서 진리표 써보면 됨

※ N input XOR는 parity gate라고도 함

정리할 책은 "Digital Design and Computer Architecture -David Harris 외 1명-" 기준입니다.


책 + 보면서 궁금한 점을 검색하여 쓸겁니다.


앞으로 순서


1. 2진수를 표현 하는 방법


2. 논리게이트 란?


3. 조합논리

- 부울 식

- 카르노 맵


4. 논리 디자인

- 래치와 플리플롭

- FSM


5. 하드웨어의 표현


6. 디지털 빌딩 블록

- 연산 회로

- 메모리 어레이


7. 파이프라이닝


7. 메모리 시스템

- 메모리 종류

- 캐시



앞으로 진행하면서 나온다면 설명하겠지만

우선 이 책은 mips processor 기준으로 작성되었고,

앞으로 포스팅은 제가 필요하다고 생각되는 부분만 할 것이기에

프로세서나 어셈에 대해서는 잘 다루지 않을 것입니다.

문제를 풀면서 무엇이 부족한지 모르기에 좀 더 절차적으로 접근


1. 알고리즘 문제 해결을 위한 전략

1) 문제를 읽고 이해하기

- 문제가 원하는 바를 완전히 이해

- 사소한 제약조건, N값의 범위, 메모리 크기



2) 문제를 익숙한 용어로 재정의 = 재정의와 추상화

- 문제를 직관적으로 이해하기 위한 발판

- 문제의 본질만 남기고 축약 => 어떤 부분을 추상화할 것인를 선택하는 작업, 문제를 재정의하는 방법들에 대한 고찰



3) 계획 세우기

- 문제를 어떤 방식으로 해결할지, 사용할 알고리즘과 자료구조 선택


※ 문제 해결 전략 => 체계적인 접근

- 비슷한 문제를 풀어본 적이 있는가? => 원리를 이해하고 변형할 수 있는 능력

  문제의 목적을 보고 적절한 접근법을 선택하기 위해서는 문제를 분류(최적화, 경우의 수, 검색 등)하고, 각 알고리즘들이 어느 경우에 사용될 수 있는지

- 단순한 방법 => 점진적으로 개선점을 찾아가는 방법

- 수식화

- 문제를 단순화

- 그림으로

- 문제를 분해

- 뒤에서 부터 시작

- 순서를 강제

- 특정 형태의 답만 고려(답이 여러개가 나올 수 있는 경우)



4) 계획 검증하기

- 빅오, 메모리



5) 계획 수행하기

- 구현에서 유의점과 좋은 프로그램 작성


※ 좋은 코드 짜기

- 간결한 코드 - 전역변수(대회 한정)

- 코드 재사용 - 모듈화 : 항상 깔끔하게 작성하고 그것이 습관이 되도록 노력

- 표준 라이브러리 공부

- 항상 같은 형태로 프로그램 작성 - 행열, 범위, for 등

- 일관적이고 명료한 명명법 사용

- 자료를 정규화 - 각도, 시간, 분수 등 : 정규화는 프로그램이 자료를 입력 받거나 계산하자마자 바로 시행하는 것이 좋음

- 코드와 데이터 분리

  fig1 코드 처럼 데이터를 코드 안에 넣기 보다는 fig2 처럼 논리와 상관없는 데이터는 상수화

string getMonthName(int month){
   if (month == 1) return "January";
   if (month == 2) return "February";
   ...
   return "December";
}

<fig1>

const string monthName[] = { "January", "Fabruary", ..., "December" };

<fig2>


코드와 상관없는 데이터 부분은 따로 분리. 맵에서 움직일 수 있는 위치 보다 움직일 수 있는 상대좌표를 이용하는 것이 좋음

단, 오타 조심


※ 자주하는 실수

- 산술 오버플로우

  int를 벗어나는 큰 결과 또는 중간값 : 자료형을 변경, 중간값의 수식을 변경하여 초과하지 않도록 함

  무한대 - 987654321 : 2^30에 가까운 수로 어느 정도의 수가 더해지더라도 오버플로우가 안생김

  자료형의 프로모션 - 보통 부호있는 값과 없는 값이 계산될 때 : 특히 벡터의 사이즈는 부호없는 size_t를 반환함

  실수 연산 - 안쓰는게 제일 좋음. 써야 한다면 값을 늘려서 정수형으로 변환. 그것도 안되면 그냥 크게 잡는게 좋음(부동 소수점의 유효숫자)

- Out of Index

- 상수 오타

- 스택 오버플로우 - C++의 경우 지역 변수로 선언한 배열이나 클래스 인스턴스가 스택을 사용하기 때문에 조심. 그냥 전역이 제일 좋음

- 다차원 배열 인덱스 바꿔쓰기

- 최대, 최소 예외

- 연산자 우선순위

- 변수 초기화 - 입력 예제를 똑같은걸 두번 쓰면 어느 정도 피할 수 있음

- 계산 중간 결과를 출력하는 것이 디버깅을 덜 돌리게 함



6) 회고하기

- 문제를 풀 때마다 코드와 함께 자신의 경험을 기록

- 문제의 간단한 해법 + 어떤 방식으로 접근했는지 + 문제 해결을 위한 결정적 깨달음

- 오답 원인

=> 나중에 읽으면서 그때 뭘 배웠는지 되새김. 문제들 간의 공통 해법 등 파악하는데 좋음

- 다른 사람의 코드




다음 2편은 빅오에 대해



- 해당 내용은 종만북에서 가져옴 -

- 알고리즘 문제 해결 전략 1편 중 -

- 저작권 문제시 삭제하겠습니다 -

'먹고살려면 > Algorithm' 카테고리의 다른 글

3-2편 무식하게 풀기 2  (0) 2017.12.18
번외편 c/c++ 입력속도  (0) 2017.12.12
3-1편 무식하게 풀기 1  (0) 2017.12.11
2편 알고리즘 시간 복잡도 분석  (0) 2017.12.07
알고리즘 시작하기  (0) 2017.11.30

지극히 주관적이고 공부한거 안까먹고 어디서든 보고 싶은 마음에 블로그를 시작함


17년 2월 쯤 알고리즘을 시작함


백준 오프라인 강의로 시작함


저 밑바닥 구렁텅이에서 인간계로 넘어오기 위해 발버둥 치는 중임


17년 11월 현재까지 이래저래 제대로 공부한건 4개월 정도


지금부터는 종만북과 BOJ, COCI 위주로 공부할 계획


1. 종만북 - 

2. BOJ, COCI는 종만북에서 공부한 알고리즘 위주로만 풀 예정

+ Recent posts