반응형
이 포스트에서는 C++으로 작성된 각종 알고리즘들의 형식적으로 코드를 정리하였습니다.
코드를 작성할 때마다 그 형태와 구성이 달라지면 불편하기 때문에 이를 해결하고자 작성하게 되었습니다.
- 각 알고리즘은 분야별로 정리되어 있습니다. (분류된 분야가 정확하지 않을 수 있습니다.)
- 같은 분야 내에서는 웬만하면 난이도 오름차순으로 정리하고자 하였습니다.
** 개인적으로 자주 사용하는 알고리즘 위주로 정리하였습니다! (필요한 알고리즘이 없을 수도 있음)
알고리즘은 참고용으로만 봐주세요.
문제 풀이를 할 때는, 웬만해서는 직접 다시 생각해보면서 코드를 직접 작성하는 것을 추천합니다.
코드는 포스트의 가독성을 최대화하고자 접은 글에 정리하였으니, 접은 글을 펼쳐서 코드를 복사하시면 됩니다.
+ 일부 알고리즘은 C로 작성된 것도 있으니, 메모리 제한에 걸릴 경우 C++의 vector로 바꿔서 사용하시면 됩니다.
각종 라이브러리 응용
벡터 Swap Trick & 배열 초기화
더보기
int Capacity[MAX][MAX];
vector<int> Line[MAX];
fill(&Capacity[0][0], &Capacity[MAX-1][MAX], 0); // for 2 dimensional array
vector<int>().swap(Line); // for 1 dimensional vector
for(int i=0; i<MAX; i++) vector<int>().swap(Line[i]); // for 2 dimensional vector
정수론
유클리드 호제법 (최대공약수)
더보기
#include <iostream>
#include <algorithm>
using namespace std;
int GCD(int X, int Y) {
if(X < Y) swap(X, Y);
while(Y != 0) {
int Temp = X%Y;
X = Y;
Y = Temp;
}
return X;
}
int main() {
int X, Y;
cin >> X >> Y;
cout << GCD(X, Y);
}
에라토스테네스의 체 (소수 판별)
더보기
// A program to find a prime number up to N using a "Sieve of Eratosthenes".
#include <cstdio>
#include <vector>
using namespace std;
vector<int> Arr;
int main() {
int N;
scanf("%d", &N);
Arr.resize(N+1);
for(int i=2; i*i<=N; i++)
for(int j=2; i*j<=N; j++) Arr[i*j] = 1;
for(int i=1; i<=N; i++)
if(!Arr[i]) printf("%d ", i);
}
기하
Convex Hull + 회전하는 캘리퍼스
더보기
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
struct Point { long long x, y; };
Point operator-(Point A, Point B) {
Point C;
C.x = A.x - B.x;
C.y = A.y - B.y;
return C;
}
vector<Point> Points;
long long Cross(Point A, Point B, Point C) {
return A.x*(B.y-C.y) + B.x*(C.y-A.y) + C.x*(A.y-B.y);
}
bool Compare(Point A, Point B) {
long long Value = Cross(Points[0], A, B);
if(Value != 0) return Value > 0;
else if(A.y != B.y) return A.y < B.y;
else return A.x < B.x;
}
long long DistSq(Point A, Point B) {
return (A.x-B.x)*(A.x-B.x) + (A.y-B.y)*(A.y-B.y);
}
int main() {
int N;
scanf("%d", &N);
Points.resize(N+1);
for(int i=0; i<N; i++)
scanf("%lld %lld", &Points[i].x, &Points[i].y);
for(int i=1; i<N; i++)
if(Points[i].y < Points[0].y || (Points[i].y == Points[0].y && Points[i].x < Points[0].x))
swap(Points[0], Points[i]);
sort(Points.begin()+1, Points.end(), Compare);
// Convex Hull
vector<Point> Convex;
Point Temp1, Temp2, First;
Convex.push_back(Points[0]);
Convex.push_back(Points[1]);
for(int i=2; i<N*4; i++) {
while(Convex.size() >= 2) {
Temp2 = Convex.back();
Convex.pop_back();
Temp1 = Convex.back();
if(Cross(Temp1, Temp2, Points[i]) > 0) {
Convex.push_back(Temp2);
break;
}
}
Convex.push_back(Points[i]);
}
// Rotating Calipers
int Size = Convex.size(), LPoint = 0, RPoint = 0;
for(int i=0; i<Size; i++) {
if(Convex[i].x < Convex[LPoint].x) LPoint = i;
if(Convex[i].x > Convex[RPoint].x) RPoint = i;
}
int DiaSq = DistSq(Convex[LPoint], Convex[RPoint]);
Point Origin; Origin.x = 0, Origin.y = 0;
for(int i=0; i<Size; i++) {
if(Cross(Origin, Convex[(LPoint+1)%Size]-Convex[LPoint], Convex[RPoint]-Convex[(RPoint+1)%Size]) > 0)
LPoint = (LPoint + 1)%Size;
else RPoint = (RPoint + 1)%Size;
if(DistSq(Convex[LPoint], Convex[RPoint]) > DiaSq)
DiaSq = DistSq(Convex[LPoint], Convex[RPoint]);
}
printf("%lld\n", DiaSq);
}
다각형 내부의 점 판정
더보기
#include <cstdio>
#include <vector>
#include <stack>
#include <algorithm>
#define N 3
using namespace std;
struct Point { int x, y; };
Point operator-(Point A, Point B) {
Point C;
C.x = A.x - B.x, C.y = A.y - B.y;
return C;
}
vector<Point> Poly;
int Abs(int A) { return A>=0?A:-A; }
int Cross(Point A, Point B, Point C) {
Point AB = B-A;
Point AC = C-A;
return AB.x*AC.y - AB.y*AC.x;
}
bool CompareCross(Point A, Point B) {
int Value = Cross(Poly[0], A, B);
if(Value) return Value > 0;
else if(A.y != B.y) return A.y < B.y;
else return A.x < B.x;
}
bool isInPoly(vector<Point> &Poly, Point P) {
int Size = Poly.size();
Point Origin; Origin.x = 0, Origin.y = 0;
Point LeftV = Poly[Size-1] - Poly[0];
Point RightV = Poly[1] - Poly[0];
Point PointV = P - Poly[0];
if(Cross(Origin, LeftV, PointV) > 0) return false;
if(Cross(Origin, RightV, PointV) < 0) return false;
int Left = 1, Right = Size - 1;
while(Left+1 < Right) {
int Mid = (Left + Right)/2;
Point MidV = Poly[Mid] - Poly[0];
if(Cross(Origin, MidV, PointV) > 0) Left = Mid;
else Right = Mid;
}
Point V1 = P - Poly[Left];
Point V2 = Poly[Left+1] - P;
return Cross(Origin, V1, V2) <= 0;
}
int main() {
Poly.resize(N);
for(int i=0; i<N; i++) scanf("%d %d", &Poly[i].x, &Poly[i].y);
for(int i=1; i<N; i++)
if(Poly[i].y < Poly[0].y || (Poly[i].y == Poly[0].y && Poly[i].x < Poly[0].x))
swap(Poly[0], Poly[i]);
sort(Poly.begin()+1, Poly.end(), CompareCross);
stack<Point> Convex;
Convex.push(Poly[0]);
Convex.push(Poly[1]);
for(int i=2; i<N; i++) {
while(Convex.size() >= 2) {
Point Temp2 = Convex.top();
Convex.pop();
Point Temp1 = Convex.top();
if(Cross(Temp1, Temp2, Poly[i]) > 0) {
Convex.push(Temp2);
break;
}
}
Convex.push(Poly[i]);
}
vector<Point> SortedPoly;
int Size = Convex.size();
SortedPoly.resize(Size);
for(int i=Size-1; i>=0; i--) {
SortedPoly[i] = Convex.top();
Convex.pop();
}
int M, Cnt = 0;
scanf("%d", &M);
for(int i=0; i<M; i++) {
Point P;
int x, y;
scanf("%d %d", &x, &y);
P.x = x, P.y = y;
if(isInPoly(SortedPoly, P)) Cnt++;
}
printf("%.1lf\n", (double)Abs(Cross(SortedPoly[0], SortedPoly[1], SortedPoly[2]))*0.5);
printf("%d", Cnt);
}
자료 구조
세그먼트 트리 (Min, Max)
더보기
#include <cstdio>
#include <vector>
#include <algorithm>
#define INF 1000001
using namespace std;
vector<int> Min, Max;
void updateTree(int Node, int Begin, int End, int Index, int Value) {
if(Index < Begin || Index > End) return;
if(Begin == End) {
Min[Node] = Max[Node] = Value;
return;
}
int Mid = (Begin + End)/2;
updateTree(Node*2, Begin, Mid, Index, Value);
updateTree(Node*2+1, Mid+1, End, Index, Value);
Min[Node] = min(Min[Node*2], Min[Node*2+1]);
Max[Node] = max(Max[Node*2], Max[Node*2+1]);
}
int findMin(int Node, int Begin, int End, int Left, int Right) {
if(Left > End || Right < Begin) return INF;
if(Left <= Begin && Right >= End) return Min[Node];
int Mid = (Begin + End)/2;
return min(findMin(Node*2, Begin, Mid, Left, Right), findMin(Node*2+1, Mid+1, End, Left, Right));
}
int findMax(int Node, int Begin, int End, int Left, int Right) {
if(Left > End || Right < Begin) return 0;
if(Left <= Begin && Right >= End) return Max[Node];
int Mid = (Begin + End)/2;
return max(findMax(Node*2, Begin, Mid, Left, Right), findMax(Node*2+1, Mid+1, End, Left, Right));
}
int main() {
int N, Q, H, Left, Right;
scanf("%d %d", &N, &Q);
Min.resize(N*4+1), Max.resize(N*4+1);
for(int i=1; i<=N; i++) {
scanf("%d", &H);
updateTree(1, 1, N, i, H);
}
for(int i=0; i<Q; i++) {
scanf("%d %d", &Left, &Right);
printf("%d\n", findMax(1, 1, N, Left, Right)-findMin(1, 1, N, Left, Right));
}
}
그래프
DFS, BFS
더보기
#include <cstdio>
#include <algorithm>
#include <vector>
#include <queue>
#define MAX 1000
using namespace std;
int N;
vector<int> Graph[MAX+1];
vector<bool> Visit;
void DFS(int V) {
Visit[V] = true;
printf("%d ", V);
for(int i=0; i<Graph[V].size(); i++) {
int Next = Graph[V][i];
if(!Visit[Next]) DFS(Next);
}
}
void BFS(int V) {
Visit[V] = true;
queue<int> Queue;
Queue.push(V);
while(!Queue.empty()) {
int Pop = Queue.front();
printf("%d ", Pop);
Queue.pop();
for(int i=0; i<Graph[Pop].size(); i++) {
int Next = Graph[Pop][i];
if(!Visit[Next]) {
Visit[Next] = true;
Queue.push(Next);
}
}
}
}
int main() {
int M, Begin, X, Y;
scanf("%d %d %d", &N, &M, &Begin);
Visit.resize(N+1);
for(int i=0; i<M; i++) {
scanf("%d %d", &X, &Y);
Graph[X].push_back(Y);
Graph[Y].push_back(X);
}
// for(int i=1; i<=N; i++) sort(Graph[i].begin(), Graph[i].end()); // Use when need sorting
DFS(Begin); printf("\n");
fill(Visit.begin(), Visit.end(), false);
BFS(Begin);
}
트리 지름
더보기
#include <iostream>
#include <vector>
using namespace std;
int max_cost = 0, deep_node = 1;
vector<pair<int, int>> node[100005];
void DFS(int cur, int prev, int cost) {
if(cost > max_cost) {
max_cost = cost;
deep_node = cur;
}
for(int i=0; i<node[cur].size(); i++)
if(node[cur][i].first != prev) DFS(node[cur][i].first, cur, cost+node[cur][i].second);
}
int main() {
int V, a, b, c;
cin >> V;
for(int i=0; i<V; i++) {
cin >> a;
while(1) {
cin >> b;
if(b == -1) break;
cin >> c;
node[a].push_back(make_pair(b, c));
}
}
DFS(1, 0, 0);
max_cost = 0;
DFS(deep_node, 0, 0);
cout << max_cost;
}
LCA (최소 공통 조상)
더보기
#include <cstdio>
#include <vector>
#define MAX 100001
using namespace std;
int Parent[MAX][20], Depth[MAX], H = 0;
vector<int> Line[MAX];
void findParent(int Par, int Node, int Dep) {
if(!Line[Node].size()) return;
Parent[Node][0] = Par;
Depth[Node] = Dep;
for(int i=0; i<Line[Node].size(); i++)
if(Line[Node][i] != Par) findParent(Node, Line[Node][i], Dep+1);
}
int findLCA(int A, int B) {
if(Depth[A] != Depth[B]) {
if(Depth[A] < Depth[B]) swap(A, B);
int Diff = Depth[A] - Depth[B];
for(int i=0; Diff>0; i++) {
if(Diff%2) A = Parent[A][i];
Diff >>= 1;
}
}
if(A != B) {
for(int i=H; i>=0; i--)
if(Parent[A][i] != 0 && Parent[A][i] != Parent[B][i]) {
A = Parent[A][i];
B = Parent[B][i];
}
A = Parent[A][0];
}
return A;
}
int main() {
int N, M, A, B;
scanf("%d", &N);
for(int i=0; i<N-1; i++) {
scanf("%d %d", &A, &B);
Line[A].push_back(B);
Line[B].push_back(A);
}
findParent(0, 1, 0);
int temp = N;
while(temp > 1) {
temp /= 2;
H++;
}
for(int i=1; i<=H; i++)
for(int j=2; j<=N; j++)
if(Parent[j][i-1]) Parent[j][i] = Parent[Parent[j][i-1]][i-1];
scanf("%d", &M);
for(int i=0; i<M; i++) {
scanf("%d %d", &A, &B);
printf("%d\n", findLCA(A, B));
}
}
최대 유량 (Network Flow)
더보기
#include <bits/stdc++.h>
#define MAX 105
#define INF 1e9
using namespace std;
vector<int> Line[MAX];
int Capacity[MAX][MAX], Flow[MAX][MAX];
void AddEdge(int From, int To) {
Line[From].push_back(To), Line[To].push_back(From);
Capacity[From][To] = 1;
}
int MaxFlow(int Sour, int Sink) {
int FlowSum = 0;
while(true) {
int Parent[MAX]; fill(Parent, Parent+MAX, -1);
queue<int> Queue; Queue.push(Sour);
while(!Queue.empty() && Parent[Sink] == -1) {
int Curr = Queue.front(); Queue.pop();
for(int i=0; i<Line[Curr].size(); i++) {
int Next = Line[Curr][i];
if(Capacity[Curr][Next] - Flow[Curr][Next] > 0 && Parent[Next] == -1) {
Queue.push(Next);
Parent[Next] = Curr;
}
}
}
if(Parent[Sink] == -1) break;
int Amount = INF;
for(int i=Sink; i!=Sour; i=Parent[i])
Amount = min(Amount, Capacity[Parent[i]][i] - Flow[Parent[i]][i]);
for(int i=Sink; i!=Sour; i=Parent[i]) {
Flow[Parent[i]][i] += Amount;
Flow[i][Parent[i]] -= Amount;
}
FlowSum += Amount;
}
return FlowSum;
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
int N, M, Sour = 101, Sink = 102;
cin >> N >> M;
for(int i=1; i<=N; i++) AddEdge(Sour, i);
for(int i=1; i<=M; i++) AddEdge(50+i, Sink);
}
최소 비용 최대 유량 (MCMF)
더보기
#include <cstdio>
#include <vector>
#include <queue>
#include <algorithm>
#define MAX 605
#define INF 1000000000
using namespace std;
int Capacity[MAX][MAX], Flow[MAX][MAX], SinCost[MAX][MAX];
vector<int> Line[MAX];
void AddLine(int From, int To, int Cap, int Cost) {
Line[From].push_back(To), Line[To].push_back(From);
Capacity[From][To] = Cap;
SinCost[From][To] = Cost, SinCost[To][From] = -Cost;
}
int MCMF(int Sour, int Sink) {
int CostSum = 0;
while(true) {
int Prev[MAX], Cost[MAX];
fill(Prev, Prev+MAX, -1);
fill(Cost, Cost+MAX, INF);
Cost[Sour] = 0;
queue<int> Queue;
Queue.push(Sour);
bool isInQueue[MAX];
fill(isInQueue, isInQueue+MAX, false);
isInQueue[Sour] = true;
while(!Queue.empty()) {
int Curr = Queue.front();
Queue.pop();
isInQueue[Curr] = false;
for(int i=0; i<Line[Curr].size(); i++) {
int Next = Line[Curr][i];
if(Capacity[Curr][Next] - Flow[Curr][Next] > 0
&& Cost[Curr] + SinCost[Curr][Next] < Cost[Next]) {
Cost[Next] = Cost[Curr] + SinCost[Curr][Next];
Prev[Next] = Curr;
if(!isInQueue[Next]) {
Queue.push(Next);
isInQueue[Next] = true;
}
}
}
}
if(Prev[Sink] == -1) break;
int Amount = INF;
for(int i=Sink; i!=Sour; i=Prev[i])
Amount = min(Amount, Capacity[Prev[i]][i] - Flow[Prev[i]][i]);
for(int i=Sink; i!=Sour; i=Prev[i]) {
CostSum += Amount*SinCost[Prev[i]][i];
Flow[Prev[i]][i] += Amount;
Flow[i][Prev[i]] -= Amount;
}
}
return CostSum;
}
int main() {
int T, N, M, Start, Sour, Sink, From, To;
scanf("%d", &T);
for(int t=0; t<T; t++) {
fill(&Capacity[0][0], &Capacity[MAX-1][MAX], 0);
fill(&Flow[0][0], &Flow[MAX-1][MAX], 0);
fill(&SinCost[0][0], &SinCost[MAX-1][MAX], INF);
for(int i=0; i<MAX; i++) vector<int>().swap(Line[i]);
scanf("%d %d", &N, &M);
Start = 2*N+1, Sour = 2*N+2, Sink = 2*N+3;
AddLine(Sour, Start, 2, 0);
for(int i=1; i<=N; i++) {
AddLine(Start, i, 1, 0);
AddLine(i, i+N, 1, -1);
AddLine(i+N, Sink, 1, 0);
}
for(int i=0; i<M; i++) {
scanf("%d %d", &From, &To);
AddLine(From+N, To, 1, 0);
}
printf("%d\n", -MCMF(Sour, Sink));
}
}
DP
투 포인터 (부분합)
더보기
#include <cstdio>
#define INF 100005
using namespace std;
int main() {
int N, S, left = 0, right = 0, sum = 0, length = INF;
int arr[100005] = {0, };
scanf("%d %d", &N, &S);
for(int i=0; i<N; i++) scanf("%d", &arr[i]);
sum = arr[0];
while(left <= right && right < N) {
if(sum < S) sum += arr[++right];
else if(sum == S) {
if(right-left+1 < length) length = right-left+1;
sum += arr[++right];
}
else if(sum > S) {
if(right-left+1 < length) length = right-left+1;
sum -= arr[left++];
}
}
if(length == INF) printf("0");
else printf("%d", length);
}
문자열
해시맵
더보기
#include <iostream>
#include <string>
#include <map>
using namespace std;
int main() {
int N, M;
string id, pw;
map <string, string> account;
cin >> N >> M;
for(int i=0; i<N; i++) {
cin >> id >> pw;
account[id] = pw;
}
for(int i=0; i<M; i++) {
cin >> id;
cout << account[id] << '\n';
}
}
KMP (문자열 탐색)
더보기
#include <iostream>
#include <vector>
#include <string>
using namespace std;
vector<int> GetPi(string Pattern) {
vector<int> Pi(Pattern.length());
for(int i=1, j=0; i<Pattern.length(); i++) {
while(j>0 && Pattern[i] != Pattern[j]) j = Pi[j-1];
if(Pattern[i] == Pattern[j]) Pi[i] = ++j;
}
return Pi;
}
vector<int> KMP(string Str, string Pattern) {
vector<int> Pi = GetPi(Pattern), Pos;
for(int i=0, j=0; i<Str.length(); i++) {
while(j>0 && Str[i] != Pattern[j]) j = Pi[j-1];
if(Str[i] == Pattern[j]) {
if(j == Pattern.length()-1) {
Pos.push_back(i-j);
j = Pi[j];
}
else j++;
}
}
return Pos;
}
int main() {
string Str, Pattern;
cin >> Str >> Pattern;
vector<int> Pos = KMP(Str, Pattern);
cout << !Pos.empty();
}
반응형
'알고리즘 > 알고리즘 공부 내용 정리' 카테고리의 다른 글
우선순위 큐를 활용한 다익스트라 알고리즘 O(E log V) (0) | 2022.03.28 |
---|---|
[웹 사이트 만들기] 웹 호스팅하기, 도메인(내 주소) 생성, 페이지 만들기 (0) | 2022.03.14 |
[C++ 백준 풀이] LCA, 최소 공통 조상 알고리즘 (11438번 : LCA 2 / 11437번 : LCA) (0) | 2021.12.16 |
C언어 모든 정렬 알고리즘 가장 간단한 코드 정리 (순차, 버블, 삽입, 선택, 병합, 퀵 정렬) (0) | 2021.11.17 |
[C언어 재귀함수] 10진수를 2진수로 변환하는 2줄짜리 함수 코드 (2) | 2021.08.08 |