문제

RGB거리에는 집이 N개 있다. 거리는 선분으로 나타낼 수 있고, 1번 집부터 N번 집이 순서대로 있다.

집은 빨강, 초록, 파랑 중 하나의 색으로 칠해야 한다. 각각의 집을 빨강, 초록, 파랑으로 칠하는 비용이 주어졌을 때, 아래 규칙을 만족하면서 모든 집을 칠하는 비용의 최솟값을 구해보자.

1번 집의 색은 2번, N번 집의 색과 같지 않아야 한다.
N번 집의 색은 N-1번, 1번 집의 색과 같지 않아야 한다.
i(2 ≤ i ≤ N-1)번 집의 색은 i-1, i+1번 집의 색과 같지 않아야 한다.

입력

첫째 줄에 집의 수 N(2 ≤ N ≤ 1,000)이 주어진다. 둘째 줄부터 N개의 줄에는 각 집을 빨강, 초록, 파랑으로 칠하는 비용이 1번 집부터 한 줄에 하나씩 주어진다. 집을 칠하는 비용은 1,000보다 작거나 같은 자연수이다.

출력

첫째 줄에 모든 집을 칠하는 비용의 최솟값을 출력한다.

예제 입력 1

1
2
3
4
3
26 40 83
49 60 57
13 89 99

예제 출력 1

1
110

예제 입력 2

1
2
3
4
3
1 100 100
100 1 100
100 100 1

예제 출력 2

1
3

예제 입력 3

1
2
3
4
3
1 100 100
100 100 100
1 100 100

예제 출력 3

1
201

예제 입력 4

1
2
3
4
5
6
7
6
30 19 5
64 77 64
15 19 97
4 71 57
90 86 84
93 32 91

예제 출력 4

1
208

예제 입력 5

1
2
3
4
5
6
7
8
9
8
71 39 44
32 83 55
51 37 63
89 29 100
83 58 11
65 13 15
47 25 29
60 66 19

예제 출력 5

1
253

내 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
const [N, ...input] = require("fs")
.readFileSync("/dev/stdin")
.toString()
.trim()
.split("\n");
const n = +N;
const costs = input.map((elem) => elem.split(" ").map(Number));

const MAX = 100001;
let answer = MAX;

let dp = Array.from({ length: n + 1 }, () => [0, 0, 0]);

for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
if (i === j) dp[0][j] = costs[0][j];
else dp[0][j] = MAX;
}

for (let j = 1; j < n; j++) {
dp[j][0] = Math.min(dp[j - 1][1], dp[j - 1][2]) + costs[j][0];
dp[j][1] = Math.min(dp[j - 1][0], dp[j - 1][2]) + costs[j][1];
dp[j][2] = Math.min(dp[j - 1][0], dp[j - 1][1]) + costs[j][2];
}

for (let j = 0; j < 3; j++) {
if (i === j) continue;
answer = Math.min(answer, dp[n - 1][j]);
}
}

console.log(answer);

해설

RGB 거리 문제와는 다르게 첫번째 선택한 색상을 마지막에서도 선택하면 안되므로 첫번째 선택한 색상을 기억해두도록 접근하자.

예를 들어 첫번째 색상을 R로 선택했다고 하면 나머지 G,B 색상은 선택하지 못하도록 최대값으로 설정해준다.

이후에 다음 집에서는 R을 제외한 나머지 2가지 색상 중 작은 값을 선택하고 해당 집의 색상 비용을 더해줘서 DP 배열을 완성 시켜나간다.

그리하여 DP 배열이 완성되고 나면 DP 배열의 최종 인덱스에 위치한 배열 중 가장 작은 값을 answer 변수에 저장해둔다.

이렇게 첫번째 집을 R로 설정한 경우, G로 설정한 경우, B로 설정한 경우 총 3번을 진행하고 나서 최종적으로 answer 값을 출력해주면 된다.

댓글 공유

자료구조

자료구조는 효율적으로 데이터를 관리하고 수정, 삭제, 탐색, 저장할 수 있는 데이터 집합이다.

어떤 비즈니스 로직을 처리할 때 가장 효과적인 자료구조를 찾아서 쓰는 것이 중요하기 때문에 자료구조를 명확하게 알아야한다.

자료구조를 설명하기 위해 C++은 이해하기 쉬운 언어이기 때문에 자료구조 공부는 C++로 할 것이다.

1
2
3
4
5
6
7
8
#include <bits/stdc++.h> // 1
using namespace std; // 2
string a; // 3
int main(){ // 4
cin >> a; // 5
cout << a << '\n'; // 6
return 0; // 7
}
  1. 헤더 파일. import할 때 사용한다. bits/stdc++.h 는 모든 표준 라이브러리를 의미한다.

  2. std라는 네임스페이스 사용하겠다. cin, cout 사용할 때 원래는 std::cin처럼 네임스페이스 달아서 사용해야하는데 이를 기본으로 설정한다는 뜻이다.

  3. 문자열 선언. <타입> <변수명> 이런식으로 선언한다. 예를들어 string a = 'Wix' 이렇게 선언했다면, a는 lvalue, Wix는 rvalue라고 한다. lvalue는 추후 다시 사용될 수 있는 변수이고 rvalue는 한 번 쓰고 다시 사용되지 않는 변수이다.

  4. 입력. 대표적으로 cin, scanf가 있다.

  5. 출력. 대표적으로 cout, printf가 있다.

  6. return 0은 프로세스가 정상적으로 마무리 됨을 뜻한다.

int는 4바이트 정수를 사용할 때 사용되는 타입이다. 표현범위는 -2,147,483,648 ~ 2,147,483,647 입니다.

시간복잡도

시간복잡도란, 입력 크기에 대해 어떤 알고리즘이 실행되는데 걸리는 시간이다. 직접적인 시간을 측정하는 것이 아닌 주요 로직의 반복횟수를 중점으로 측정된다.

왜냐하면 직접적인 시간은 여러가지 요인에 따라 변경될 수 있기 때문이다.

1
2
3
4
5
6
7
8
9
10
11
for(int i = 0; i < 10; i++){
for(int j =0; j < n; j++){
for(int k = 0; k < n; k++){
if(true) cout << k << '\n';
}
}
}

for(int i = 0; i < n; i++){
if(true) cout << i << '\n';
}

위 코드에서 시간 복잡도는 10n^2+n이다.

빅오표기법(Big - O)

빅오표기법은 복잡도에 영향을 가장 많이 끼치는 항의 상수인자를 제거하고 나머지 항을 없애서 복잡도를 표기하는 표기법이다.

앞선 예시를 빅오표기법으로 나타내면 O(n^2)이다.

여기서 영향을 가장 많이 끼친다는 의미는 입력 크기가 커질수록 증가속도가 가장 큰 것을 의미한다.

예를 들어 n^2은 1,4,9,16,25 이런식으로 증가하는데, n은 1,2,3,4,5 이런식을로 증가하기 때문에 영향이 가장 큰 n^2 항의 상수 인자를 제거하여 빅오표기법으로 나타낸 것이다.

빅오표기법 차트는 외워두자!

n! > 2^n > n^2 > nlogn > n > logn > 1 순입니다.

Big-O chart

상수시간 시간복잡도 O(1)

상수시간 시간 복잡도는 입력 크기와 상관없이 일정한 시간복잡도를 가지는 것을 말한다.

  1. 입력과 출력
1
cin, cout, scanf, printf
  1. 곱하기
1
a[2] *= 2;
  1. 간단한 비교 if 문
1
2
3
if (a[0] == 2) {
// 로직
}
  1. 배열 인덱스 참조
1
2
int a[3] = {1,2,3};
int b = a[2]

댓글 공유

node.js

node.js란 비동기적 이벤트 주도 방식, 논블로킹 I/O 모델을 사용하는 구글의 V8 엔진을 장착한 자바스크립트 런타임이다.

런타임이란, 프로그램이 실행될 때 그 프로그램이 머무는 공간을 의미한다. 때문에 브라우저는 자바스크립트 런타임이라고도 한다.

이와 동일하게 node.js 또한 자바스크립트 런타임이므로 자바스크립트로 만든 프로그램을 실행할 수 있다.

이번에는 node.js로 서버를 만들어서 API를 구현해보는 예시를 해보자.

실습

  1. nodejs를 설치한다.

  2. json 파일과 서버파일을 생성한다.

1
2
3
4
5
// a.json
{
"name": "Wix",
"tall": "178"
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// b.js
import express from "express";
import fs from "fs";

const app = express();
const port = 3000;
app.get("/", (req, res) => {
const f = JSON.parse(fs.readFileSync("a.json", { encoding: "utf-8" }));
const data = {
name: f.name,
tall: f.tall,
};
res.send(data);
});
app.listen(port, () => {
console.log(`http://127.0.0.1:${port}`);
});
  1. express 모듈 설치
1
npm install express

express는 node.js에서 동작하는 웹 프레임워크이다. 라우팅, 미들웨어, 정적자원서버 설정이 쉬운 장점이 있다.

  1. 터미널로 node 프로그램을 실행해본다.
1
node b.js

get() 메서드에 설정한 경로 /로 get 요청이 보내졌고 서버에서는 name, tall이 담긴 자바스크립트 객체 데이터가 응답으로 전송되었다.

앞서 API의 특징을 설명할 때, 파일 내부가 변경되더라도 API를 변경되지 않도록 설계할 수 있다고 하였다.

a.json 파일 내용을 바꾸더라도 API를 바꿔줄 필요가 없다.

댓글 공유

API

API란, 둘 이상의 컴퓨터 프로그램이 서로 통신하는 방법이자 컴퓨터 사이에 있는 중계 계층을 의미한다.

API는 어떻게 통신할 것인지, 어떤 데이터를 주고 받을 것인지 등에 대한 방법(HTTP, HTTPS 프로토콜 중 어떤 거 사용할지, GET인지 POST인지 등)이 정의된 중계 계층이다.

API 특징

  • 제공자는 본인이 원하는 부분만 드러낼 수 있다.
  • 사용자는 해당 서비스가 어떻게 구현되는지 알 필요없이 필요한 정보만 받을 수 있다.
  • OPEN API의 경우 애플리케이션 개발 과정을 단순화 시켜주어 개발 시간과 비용을 절약할 수 있다.
  • API를 만들고 나서 내부 프로세스가 수정될 때마다 매번 API를 수정해줄 필요가 없다.
  • 제공자는 데이터를 한곳에 모을 수 있다. 예를 들어 방문자 수, 클릭수 등을 집계하고 싶을 때 해당 API를 만들고 이벤트가 발생할 때 해당 API를 호출하여 데이터를 한 곳에 모을 수 있다.
  • 제공자의 경우 API를 이용해 제 3자가 만든 앱을 통해 데이터를 수집하여 해당 서비스 확장할 수도 있고 홍보에도 도움이 된다.

API 종류

  • private: 내부적으로 사용. 주고 해쉬키를 기반으로 서버와 서버간 통신에 사용된다.
  • public: 모든 사람이 사용. 많은 트래픽 방지하기 위해 하루 요청 수 제한.

댓글 공유

JSON

JavaScript 객체 문법으로 구조화된 데이터를 표현하기 위한 표준 포맷이다.

모든 서비스와 애플리케이션은 데이터를 기반으로 그것을 보여주거나 뒤에서 다루면서 데이터를 많이 사용하게된다.

세상의 모든 정형화된 데이터만 있다면 편리하겠지만, 그렇지 않은 복잡한 데이터도 많다.

예를 들어, 아래와 같은 내용을 데이터로 표현하려면 복잡하다.

Wix

  • 나이: 29
  • 좋아하는 것: 자전거타기(로드), 노래부르기(발라드)

이런 데이터를 컴퓨터도, 사람도 이해하기 쉽게 표현한 것이 바로 JSON이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"Wix": {
"age": 29,
"Likes": [
{
"name": "Riding Bike",
"type": "Road"
},
{
"name": "Sing a song",
"type": "Ballad"
}
]
}
}

특징

  • key:value 형태
  • {} 중괄호로 감싼다.
  • key, value에 “”만 사용가능하다.
  • 자바스크립트와 호환이 좋다.
  • 각 객체가 다른 타입이어도 괜찮다.
  • value에 메서드와 undefined가 올 수 없다. 이외의 수, 문자열, 불리언, 배열, 객체, null 값은 올 수 있다.
  • 프로그래밍 언어나 플랫폼에 독립적이기 때문에 서로 다른 시스템 간의 데이터 교환시 유용하다. ex) API, config 파일

XML

JSON과 비교하면 중괄호 대신 열린 태그와 닫힌 태그 구조로 이루어진 데이터 포맷이 XML이다.

1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="UTF-8"?> <!-- 프롤로그 -->
<Wix>
<age>29</age>
<Likes>
<Like>
<name>Riding Bike</name> <type>Road</type>
</Like>
<Like>
<name>Sing a song</name> <type>Ballad</type>
</Like>
</Likes>
</Wix>

특징

  • 최상위 태그는 하나만 사용해야한다.
  • JSON에 비해 무겁다. JSON에 비해 닫힌 태그까지 들어가서 2번씩 들어간다.

sitemap.xml

XML의 대표적인 예시로는 SEO에 사용되는 sitemap.xml이 있다.

사이트가 매우 크거나 서로 링크가 종속적으로 연결되어 있지 않다면 크롤러가 일부 페이지를 누락하는 일이 발생하는데 이를 방지하기 위해 sitemap.xml를 사용한다.

댓글 공유

pseudo-class

요소의 특정한 상태를 정의하기 위해 사용하는 CSS 속성이다.

  • 사용자가 마우스를 올렸을 때, 요소를 스타일링 하기
  • 방문한 링크와 미방문 링크 스타일 구분하기
  • focus가 잡혔을 때, 요소 스타일 주기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/* unvisited link */
a:link {
color: #ff0000;
}

/* visited link */
a:visited {
color: #00ff00;
}

/* mouse over link */
a:hover {
color: #ff00ff;
}

/* selected link */
a:active {
color: #0000ff;
}

a:hover는 a:link, a:visited 속성 이후에 선언되어야한다. 또한 a:active 속성은 a:hover 속성 이후에 선언되어야 한다.

:first-child pseudo-class

요소의 첫번째 자식을 선택하는 선택자이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!DOCTYPE html>
<html>
<head>
<style>
p:first-child {
color: blue;
}
</style>
</head>
<body>
<p>This is some text.</p>
<p>This is some text.</p>

<div>
<p>This is some text.</p>
<p>This is some text.</p>
</div>
<section>
<p>this is first element</p>
<p>this is second element</p>
</section>
</body>
</html>

first-child

이 외에도 많은 pseudo-class들이 있으니 필요하면 찾아서 사용하자.

pseudo-element

요소의 특정 부분을 스타일링 하기 위해 사용하는 CSS 속성이다.

  • 요소의 첫번째 줄이나 첫문자를 스타일링 하기
  • 요소 content의 이전이나 이후에 content를 삽입하기

::first-line

첫번째 줄의 특별한 스타일링을 추가하기 위해 사용한다.

  • block level 요소에만 설정 가능하다.
1
2
3
4
p::first-line {
color: #ff0000;
font-variant: small-caps;
}

::first-letter

첫번째 문자를 스타일링 하는데 사용된다.

  • block level 요소에만 설정 가능하다.
1
2
3
4
p::first-letter {
color: #ff0000;
font-size: xx-large;
}

::before

요소의 content 이전에 어떤 content를 삽입하기 위해 사용한다.

1
2
3
h1::before {
content: url(smiley.gif);
}

before

::after

요소의 content 이후에 어떤 content를 삽입하기 위해 사용한다.

1
2
3
h1::after {
content: url(smiley.gif);
}

::selection

사용자에 의해 선택된 부분을 스타일링한다. 아래는 드래그하여 텍스트를 선택하였을 때의 상황이다.

1
2
3
4
::selection {
color: red;
background: yellow;
}

selection

댓글 공유

combinators 셀렉터 조합

4가지의 셀렉터 조합이 있다.

  • 자손(descendant) 셀렉터 (space)
  • 자식(child) 셀렉터
  • 인접한 형제 셀렉터 (+)
  • 두루두루의 형제 셀렉터 (~)

descendant 셀렉터

특정 요소의 자손인 모든 요소와 매치되는 셀렉터이다.

아래 예시는 div 태그 내부의 모든 p 태그를 선택하는 예시이다.

1
2
3
div p {
background-color: yellow;
}

child 셀렉터

해당 요소의 모든 자식들을 선택하는 셀렉터이다.

아래 예시는 div 태그 내부의 모든 p 태그 자식들을 선택한다.

1
2
3
div > p {
background-color: yellow;
}

child와 descendet의 차이는 descendent는 자신 내부의 모든 자식 손자 증손자 등 모든 자손을 포함하지만, child는 딱 1 level의 자식들만 선택한다.

인접한 형제 셀렉터 (+)

다른 요소와 직접적으로 인접한 요소를 선택하기 위해 사용된다.

1
2
3
div + p {
background-color: yellow;
}

두루두루 형제 셀렉터 (~)

같은 레벨에 있는 형제 요소를 모두 선택한다.

1
2
3
div ~ p {
background-color: yellow;
}

댓글 공유

align

div 와 같은 block 요소를 수평으로 가운데 배치하려면 margin: auto;를 사용하였다.

1
2
3
4
5
6
.center {
margin: auto;
width: 50%;
border: 3px solid green;
padding: 10px;
}

하지만 내부의 텍스트를 가운데 정렬하기 위해서는 text-align: center;를 사용한다.

1
2
3
4
.center {
text-align: center;
border: 3px solid green;
}

이미지 가운데 정렬

image를 가운데 정렬하기 위해서는 block 요소로 바꾸고 width를 설정해준 뒤 margin:auto; 속성을 사용한다.

1
2
3
4
5
6
img {
display: block;
margin-left: auto;
margin-right: auto;
width: 40%;
}

좌우 정렬 - position 속성

좌우 정렬을 위해서 position:absolute; 속성을 사용할 수 있다.

1
2
3
4
5
6
7
.right {
position: absolute;
right: 0px;
width: 300px;
border: 3px solid #73ad21;
padding: 10px;
}

position:absolute 속성은 기본 flow를 제거하므로 다른 요소에 오버랩 될 수 있다.

clearfix 팁

만약, 요소가 요소를 감싸는 컨테이닝 블록보다 길고 이것이 float 속성을 가졌다면, 해당 요소는 컨테이너의 외부로 넘칠 것이다. 이를 해결하기 위해서 clearfix 속성을 사용한다.

해당 컨테이닝 블록에다가 다음 속성을 설정한다.

1
2
3
4
5
.clearfix::after {
content: "";
clear: both;
display: table;
}

clearfix

수직 가운데 정렬 - padding

padding을 상하로 주어서 수직 가운데 정렬을 해줄 수 있다.

1
2
3
4
.center {
padding: 70px 0;
border: 3px solid green;
}

이를 text-align:center; 와 같이 쓰면 수평 수직 가운데 정렬이 가능하다.

1
2
3
4
5
.center {
padding: 70px 0;
border: 3px solid green;
text-align: center;
}

수직 가운데 정렬 - line-height

line-height 속성을 사용하여 수직 가운데 정렬을 할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
.center {
line-height: 200px;
height: 200px;
border: 3px solid green;
text-align: center;
}

/* If the text has multiple lines, add the following: */
.center p {
line-height: 1.5;
display: inline-block;
vertical-align: middle;
}

수직 가운데 정렬 - position & transform

1
2
3
4
5
6
7
8
9
10
11
12
13
.center {
height: 200px;
position: relative;
border: 3px solid green;
}

.center p {
margin: 0;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}

수직 가운데 정렬 - flexbox

flexbox는 IE10나 이전버전에서는 지원되지 않는다.

1
2
3
4
5
6
7
.center {
display: flex;
justify-content: center;
align-items: center;
height: 200px;
border: 3px solid green;
}

댓글 공유

inline-block

display:inline-block 속성은 inline 속성과 block 속성을 함께 가진다.

  • inline과 달리 상하 margin, padding이 적용된다.
  • block과 달리 요소 이후 줄바꿈이 되지 않는다. 다른 요소 옆에 배치된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
span.a {
display: inline; /* the default for span */
width: 100px;
height: 100px;
padding: 5px;
border: 1px solid blue;
background-color: yellow;
}

span.b {
display: inline-block;
width: 100px;
height: 100px;
padding: 5px;
border: 1px solid blue;
background-color: yellow;
}

span.c {
display: block;
width: 100px;
height: 100px;
padding: 5px;
border: 1px solid blue;
background-color: yellow;
}

inline-block

가장 일반적인 inline-block의 사용 예시는 수평으로 목록들을 배치할 때 사용된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
.nav {
background-color: yellow;
list-style-type: none;
text-align: center;
padding: 0;
margin: 0;
}

.nav li {
display: inline-block;
font-size: 20px;
padding: 20px;
}

navlink

댓글 공유

overflow

overflow 속성은 컨텐츠가 너무 커서 영역에 맞지 않는 부분을 설정할 때 사용한다.

또한, overflow 속성은 정확한 높이를 가진 block 요소에만 동작한다.

overflow:visible

visible이 기본값이다. 이는 잘리지 않고 요소 박스 바깥에도 렌더링된다.

1
2
3
4
5
6
div {
width: 200px;
height: 65px;
background-color: coral;
overflow: visible;
}

visible

overflow:hidden

박스를 넘치는 컨텐츠는 숨긴다.

1
2
3
div {
overflow: hidden;
}

visible

overflow:scroll

박스를 넘치는 컨텐츠를 스크롤을 통해서 보이게 한다. 이 때, overflow-x, overflow-y로 수평, 수직방향 스크롤을 각각 설정해줄 수 있다.

또한, overflow:auto; 속성은 scroll과 비슷하지만, 스크롤이 필요한 경우에만 스크롤바가 생성된다.

1
2
3
4
div {
overflow-x: hidden; /* Hide horizontal scrollbar */
overflow-y: scroll; /* Add vertical scrollbar */
}

overflow

댓글 공유

loco9939

author.bio


author.job