알고스팟 문제 링크: https://algospot.com/judge/problem/read/MINASTIRITH

 

algospot.com :: MINASTIRITH

미나스 아노르 문제 정보 문제 단 한 번도 함락된 적이 없다는 성채도시 미나스 아노르에는 반지름이 8 킬로미터나 되는 거대한 원형 성벽, 람마스 에코르가 있습니다. 도시 전체를 감싸는 이 거

algospot.com

원모양의 성벽이 있고 시야가 원모양인 초소들이 성벽위에 있을때 성벽을 빈틈없이 감시할 수 있는 초소 갯수의 최솟값을 구하는 문제이다.

먼저 초소위치를 라디안으로 구하고 초소에 감시 반지름과 초소위치를 활용하여 각 초소의 감시범위를 라디안으로 저장한다.

이때 주의할점은 성벽을 [0, 2*pi]범위의 선분으로 표현할 때 시작점(끝점)을 덮는 초소들을 하나씩 순회하면서 먼저 계산하고 나머지 초소들로 남은 성벽범위를 덮어보면서 답을 찾아야 한다는 것이다.

시작점(끝점)을 덮는 초소를 골라 성벽의 나머지 부분을 begin과 end로 표현하고 초소의 시야가 begin전에 시작해서 가장 크게 뻗어나가는 초소를 골라 begin를 갱신하는 방식으로 begin이 end이상이 될때까지 반복한다.

시작점(끝점)을 덮는 초소는 많아야 최대 두개이고, 두 개일때도 둘중에 ranges[i].first가 음수인것은 시야가 시작점으로부터 끝점방향으로 더 길고 ranges[i].second가 2*pi이상인것은 시야가 끝점으로부터 시작점 방향으로 더 길수 밖에 없다는 점에 유의하자.

 

#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
const double pi = 2.0 * acos(0);
const int INF = 987654321;
int n;
double x[100], y[100], r[100];
// <초소구역 시작 라디안각도, 초소구역 끝 라디안각도>ranges
pair<double, double>ranges[100];
// 각 초소에 대한 정보들로 ranges구성
void convertToRange() {
for (int i = 0; i < n; i++) {
// 초소 위치에 대한 라디안
double loc = fmod(atan2(y[i], x[i]) + 2 * pi, 2 * pi);
// 초소 감시 범위에 대한 라디안
double range = 2.0 * asin(r[i] / 2.0 / 8.0);
// 초소 감시범위를 ranges에 저장
ranges[i] = make_pair(loc - range, loc + range);
}
sort(ranges, ranges + n);
}
// 선형으로 문제를 푸는 함수 전방선언
int solveLinear(double begin, double end);
// 시작점(끝점)을 완전히 덮는 초소 하나를 원형으로 선택하고 나머지를 선형으로 해결
int solveCircular() {
int ret = INF;
for (int i = 0; i < n; i++)
if (ranges[i].first <= 0 || ranges[i].second >= 2 * pi) {
// 시작점(끝점)을 완전히 덮는 초소에대한 감시범위를 범위[0, 2pi]로 정규화
double begin = fmod(ranges[i].second, 2 * pi);
double end = fmod(ranges[i].first + 2 * pi, 2 * pi);
// 나머지를 선형으로 해결했을때 가장 적은 초소를 들이는 경우를 계산
ret = min(ret, solveLinear(begin, end) + 1);
}
return ret;
}
int solveLinear(double begin, double end) {
int used = 0, idx = 0;
// 범위를 완전히 덮을때까지 반복
while (begin < end) {
// 선형으로 어디까지 덮었는지 나타냄
double maxCover = -1;
while (idx < n && ranges[idx].first <= begin) {
// begin전에 시작해서 오른쪽으로 가장 크게 뻗는 초소 선택
maxCover = max(maxCover, ranges[idx].second);
idx++;
}
// begin전에 시작하는 초소가 없으면 완전히 덮을수 있는 방법 없음
if (maxCover <= begin)return INF;
// begin전에 시작하는 초고 잘 골랐으면 begin 갱신
begin = maxCover;
used++;
}
return used;
}
int main() {
int testcase;
cin >> testcase;
while (testcase--) {
cin >> n;
for (int i = 0; i < n; i++)
cin >> y[i] >> x[i] >> r[i];
convertToRange();
int result = solveCircular();
if (result == INF)
cout << "IMPOSSIBLE" << endl;
else
cout << result << endl;
}
}

코드 원본: https://github.com/sbl133/JongmanBook/blob/main/10.%20Greedy/MINASTIRITH.cpp

 

GitHub - sbl133/JongmanBook

Contribute to sbl133/JongmanBook development by creating an account on GitHub.

github.com

댓글을 통한 코드리뷰, 질문, 지적 언제든 환영입니다!

reference: 프로그래밍 대회에서 배우는 알고리즘 문제해결전략1

알고스팟 문제 링크: https://algospot.com/judge/problem/read/STRJOIN

 

algospot.com :: STRJOIN

문자열 합치기 문제 정보 문제 프로그래밍 언어 C 의 큰 문제점 중 하나는 언어 차원에서 문자열 변수형을 지원하지 않는다는 것입니다. C 에서는 문자 배열로 문자열을 표현하되 \0 (NULL) 로 문자

algospot.com

여러개의 문자열이 주어졌을때 그 중 두개의 문자열을 선택해 하나의 문자열로 병합하는 과정을 반복하여 최종적으로 하나의 문자열을 만든다.

두개의 문자열을 하나로 합칠때에는 각각을 문자열의 길이만큼 훑어야 한다. 여러개의 문자열을 하나로 만들기 위해 훑어야 하는 문자열 길이의 최솟값을 구하는 문제이다.

문자열의 길이가 짧은 순서대로 병합하는 그리디 알고리즘으로 문제를 해결할 수 있다.

문자열의 길이가 짧은 순서대로 값을 꺼내어 합을 구한후 다시 삽입하여 정렬하는 과정이 필요하므로 priority_queue를 사용하면 간단히 구현할 수 있다.

 

#include<iostream>
#include<queue>
using namespace std;
int n;
int strjoin(priority_queue<int, vector<int>, greater<int>>& pq) {
int ret = 0;
// pq에 요소가 2개이상있으면 가장짧은거 두개 꺼내서 합친걸 다시 넣는다
while (pq.size() > 1) {
int x = pq.top();
pq.pop();
int y = pq.top();
pq.pop();
ret += x + y;
pq.push(x + y);
}
return ret;
}
int main() {
int testcase;
cin >> testcase;
while (testcase--) {
// 문자열 길이를 기준으로 오름차순을 위한 우선순위 큐
priority_queue<int, vector<int>, greater<int>> pq;
int length;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> length;
pq.push(length);
}
cout << strjoin(pq) << endl;
}
}

코드 원본: https://github.com/sbl133/JongmanBook/blob/main/10.%20Greedy/STRJOIN.cpp

 

GitHub - sbl133/JongmanBook

Contribute to sbl133/JongmanBook development by creating an account on GitHub.

github.com

댓글을 통한 코드리뷰, 질문, 지적 언제든 환영입니다!

reference: 프로그래밍 대회에서 배우는 알고리즘 문제해결전략1

알고스팟 문제 링크: https://www.algospot.com/judge/problem/read/LUNCHBOX

 

algospot.com :: LUNCHBOX

Microwaving Lunch Boxes 문제 정보 문제 After suffering from the deficit in summer camp, Ainu7 decided to supply lunch boxes instead of eating outside for Algospot.com winter camp. He contacted the famous packed lunch company "Doosot" to prepare N lun

www.algospot.com

도시락의 갯수와 각 도시락마다 데우는시간, 먹는 시간을 입력으로 주어지고, 한번에 하나의 도시락을 데울 수 있으며 데운 도시락은 기다리지 않고 바로 먹는다고 했을 때, 필요한 총 식사시간을 구하는 문제이다.

모든 도시락은 무조건 1번씩 다 데워져야 되기 때문에 데우는 시간은 똑같다.

문제는 먹는시간인데 먹는시간이 오래걸리는 순서대로 데워서 바로 먹는 그리디 알고리즘을 이용하면 문제를 해결할 수 있다. 

정당성 증명으로는 최적해중에 먹는 시간이 오래걸리는 도시락을 비교적 덜걸리는 도시락보다 더 늦게 먹는 경우가 있다고 가정하자. 이때 두 도시락의 데우는 순서를 바꾸면 최적해 이하의 시간이 걸린다. 따라서 먹는 시간이 오래걸리는 순서대로 데워서 먹는 그리디 알고리즘의 정당성이 성립한다.

부분 구조 증명 또한 첫번째 도시락을 정했을 때, 나머지 도시락들에 대한 시간도 최소화 해야하므로 성립한다.

 

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int n;
// <먹는시간, 데우는시간>
vector<pair<int, int>> timeTable;
int launchbox() {
// 먹는시간을 기준으로 오래걸리는 도시락이 앞에온다
sort(timeTable.begin(), timeTable.end());
int ret = -timeTable[0].first + timeTable[0].second;
// 이전까지 선택한 도시락들의 총 데우는 시간
int warmTime = 0;
for (int i = 1; i < timeTable.size(); i++) {
int curTime = -timeTable[i].first + timeTable[i].second;
warmTime += timeTable[i-1].second;
// warmTime + 직전에 선택한 도시락을 먹는시간과
// warmTime + 현재 도시락 데우는시간 + 현재도시락 먹는시간 비교
ret = max(ret, warmTime + curTime);
}
return ret;
}
int main() {
int testcase;
cin >> testcase;
while (testcase--) {
timeTable.clear();
cin >> n;
int* warm = new int[n];
int* eat = new int[n];
for (int i = 0; i < n; i++)
cin >> warm[i];
for (int i = 0; i < n; i++)
cin >> eat[i];
// 먹는시간을 내림차순으로 정렬하기 위해 음수를 취해준다
for (int i = 0; i < n; i++)
timeTable.push_back(make_pair(-eat[i], warm[i]));
cout << launchbox() << endl;
}
}

코드 원본: https://github.com/sbl133/JongmanBook/blob/main/10.%20Greedy/LUNCHBOX.cpp

 

GitHub - sbl133/JongmanBook

Contribute to sbl133/JongmanBook development by creating an account on GitHub.

github.com

댓글을 통한 코드리뷰, 질문, 지적 언제든 환영입니다!

reference: 프로그래밍 대회에서 배우는 알고리즘 문제해결전략1

알고스팟 문제 링크: https://www.algospot.com/judge/problem/read/GENIUS

 

algospot.com :: GENIUS

지니어스 문제 정보 문제 MP3 플레이어에 들어 있는 곡들을 전부 셔플 모드로 들을 때 최대의 문제점은 서로 어울리지 않는 노래들이 갑자기 나올 수 있다는 것입니다. 끈적한 애시드 재즈를 듣

www.algospot.com

MP3에 들어있는 노래수와 노래들의 재생시간, 선호하는 노래, 특정 노래후에 다음노래가 나올확률(2차원 배열)등이 주어졌을때 K분30초 후에 선호하는 노래가 나오고 있을 확률을 구하는 문제이다.

일단 K의 범위가 [1, 1000000]이기 때문에 cache공간 문제 때문에 재귀적이 DP로는 해결할수 없을것 같았고, 평범한 반복적DP도 시간복잡도 문제때문에 사용하기 힘들어 보였다.

해답으로는 행렬 거듭제곱을 이용한 동적 계획법이 있었다.

start(time, song) = 재생을 시작한지 time분 후에 song번 노래가 재생을 시작할 확률이라하자

start(time-3)부터 start(time)까지를 포함하는 크기 4*N의 열벡터 C(time)를 정의하고 C(time+1)=W*C(time)인 W를 구하여 k만큼 거듭제곱한 후 C(0)와 곱해주면 원하는 답을 얻을수 있다.

하지만 이러한 행렬들을 관리하기 위해서는 여러가지 메서드들을 직접 정의하고 연산자들도 오버로딩 해줘야 했기 때문에 무척 까다로운 문제였다. 또한 k의 범위가 무척 크기 때문에 거듭제곱의 횟수또한 줄이기 위해 분할정복을 사용하였다.

 

#include<iostream>
#include<vector>
using namespace std;
int n, k, length[50];
double T[50][50];
// C(x) = W*C(x-1) 에서의 W를 사용하기 위한 클래스 선언
class SquareMatrix {
vector<vector<double>> v;
int size;
public:
SquareMatrix(int s) :size(s) {
v.resize(size, vector<double>(size, 0.0));
}
SquareMatrix operator*(SquareMatrix x);
double* operator[](int i);
SquareMatrix pow(int num);
void identity();
};
// SquareMatrix객체를 []연산으로 읽기위한 오버로딩
double* SquareMatrix::operator[](int i) {
return &this->v[i][0];
}
// 행렬곱을위한 *연산자 오버로딩
SquareMatrix SquareMatrix::operator*(SquareMatrix x) {
SquareMatrix ret(size);
for (int i = 0; i < size; i++)
for (int j = 0; j < size; j++)
for (int k = 0; k < size; k++)
ret.v[i][j] += this->v[i][k] * x.v[k][j];
return ret;
}
// 행과 열의 크기가 size인 단위행렬 반환
void SquareMatrix::identity() {
for (int i = 0; i < size; i++)
for (int j = 0; j < size; j++)
if (i == j)
v[i][j] = 1.0;
}
// 분할정복으로 행렬곱 연산횟수 줄이기
SquareMatrix SquareMatrix::pow(int num) {
if (num == 0) {
SquareMatrix tmp(size);
tmp.identity();
return tmp;
}
if (num % 2 == 1) return this->pow(num - 1)* (*this);
SquareMatrix tmp = this->pow(num / 2);
return tmp * tmp;
}
// k분후 나올수 있는 각 음악들의 확률을 저장한 벡터반환
vector<double> getProb2() {
SquareMatrix W(4 * n);
// 어떤 음악이 시작했을확률 = 1분후 1분전에 어떤음악이 시작했을확률
for (int i = 0; i < 3 * n; i++)
W[i][i + n] = 1.0;
// 지금 어떤 음악이 시작할 확률 == 전 음악에 재생시간만큼 전에 전 음악이 시작했을확률 * T
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
W[3 * n + i][(4 - length[j]) * n + j] = T[j][i];
// W^k 구하기
SquareMatrix WK = W.pow(k);
vector<double> ret(n);
// WK*C(0) 구하기: C(0)가(0,...,0, 1, 0,...,0)이므로 WK의 3n+1번째 열만 고려
for (int song = 0; song < n; song++)
for (int start = 0; start < length[song]; start++)
ret[song] += WK[(3 - start) * n + song][3 * n];
return ret;
}
int main() {
cout.precision(8);
int testcase;
cin >> testcase;
while (testcase--) {
int m;
cin >> n >> k >> m;
for (int i = 0; i < n; i++)
cin >> length[i];
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
cin >> T[i][j];
vector<double> v = getProb2();
int likedSong;
for (int i = 0; i < m; i++) {
cin >> likedSong;
cout << v[likedSong] << " ";
}
cout << endl;
}
}

코드 원본: https://github.com/sbl133/JongmanBook/blob/main/9.%20DP-Technic/GENIUS.cpp

 

GitHub - sbl133/JongmanBook

Contribute to sbl133/JongmanBook development by creating an account on GitHub.

github.com

댓글을 통한 코드리뷰, 질문, 지적 언제든 환영입니다!

reference: 프로그래밍 대회에서 배우는 알고리즘 문제해결전략1

알고스팟 문제 링크: https://www.algospot.com/judge/problem/read/SUSHI

 

algospot.com :: SUSHI

회전초밥 문제 정보 문제 문제 풀이 내기에서 모인 벌금이 많이 쌓여서 알고스팟 운영진들은 회식을 하러 회전초밥집에 갔습니다. 회전초밥집에 들어선 운영진들은 초밥은 먹지 않고 전략 회의

www.algospot.com

입력으로 예산과 초밥의 종류 수, 각 초밥에 가격과 선호도가 주어졌을때, 예산에 맞게 초밥을 갯수 상관없이 구매하여 구할 수 있는 최대 선호도를 출력하는 문제이다.

초밥을 종류별로 탐색하면서 (예산 - 탐색중인 초밥의 가격)을 예산으로 하는 DP를 이용하여 문제를 풀수있다.

이때 주의할 점은 예산의 범위가([1,10^9]) 너무 커서 메모이제이션을 위한 배열을 예산크기만큼 선언하기 힘들다는것이다.

DP에서 (예산 - 탐색중인 초밥의 가격)을 이용한다 했을때 (탐색중인 초밥의 가격+1)만큼의 배열만 있으면 슬라이딩윈도를 사용하여 문제를 풀기 충분할거 같다.

따라서 기존에 사용하던 재귀적인 DP가아니라 슬라이딩윈도를 사용할수있는 반복적DP를 사용하였다.

(초밥의 최대 가격이 20000원이여서 여전히 배열선언하기 부담스럽지만 문제에서 주어진 조건인 가격은 100의 배수라는 점을 이용해서 배열의 크기를 200+1까지 줄여나갈 수 있다.)

 

#include<iostream>
#include<cstring>
using namespace std;
int n, m;
int price[20], prefer[20];
// 선호도를 계산할때 budget[money-price[kind]]를 이용하면 되므로
// budget의 공간은 최대 price[kind]의 최댓값 만큼만 필요하다
int budget[201];
int sushi() {
int ret = 0;
budget[0] = 0;
for (int money = 1; money <= m; money++) {
int cand = 0;
for (int kind = 0; kind < n; kind++)
if (money >= price[kind])
// money-price[kind]만큼의 예산을 가지고 있었을때 구한 선호도의 최대합과
// prefer[kind]를 더한값을 kind별로 탐색해서 선호도의 최대합을 구한다.
cand = max(cand, budget[(money - price[kind])%201] + prefer[kind]);
//budget[money]를 budget[money-201]에 덮어씌운다.
budget[money % 201] = cand;
}
return budget[m % 201];
}
int main() {
int testcase;
cin >> testcase;
while (testcase--) {
cin >> n >> m;
m /= 100;
for (int i = 0; i < n; i++) {
cin >> price[i] >> prefer[i];
price[i] /= 100;
}
cout << sushi() << endl;
}
}

코드 원본: https://github.com/sbl133/JongmanBook/blob/main/9.%20DP-Technic/SUSHI.cpp

 

GitHub - sbl133/JongmanBook

Contribute to sbl133/JongmanBook development by creating an account on GitHub.

github.com

댓글을 통한 코드리뷰, 질문, 지적 언제든 환영입니다!

reference: 프로그래밍 대회에서 배우는 알고리즘 문제해결전략1

algospot 문제링크: https://www.algospot.com/judge/problem/read/BLOCKGAME

 

algospot.com :: BLOCKGAME

블록 게임 문제 정보 문제 시티빌과 비주얼드에 지친 진호와 현환이는 집에 굴러다니는 블럭들을 모아 새로운 게임을 하기로 했습니다. 5×5 크기의 게임판에서 시작해, 둘이 번갈아 가며 블럭을

www.algospot.com

일정부분 채워져있는 게임판이 입력으로 주어졌을때 L자모양의 3칸짜리 블록으로 주어진 게임판을 채울수 있는 경우의 수를 구하는 문제입니다.

주어진 게임판에 알맞은 모양으로 블록을 놓고 그 모양의 게임판을 재귀호출하는 방법으로 완전탐색을 이용해 문제를 풀수있습니다.

이때 주의할점은 블록을 놓는 순서에 따라 똑같은 경우를 중복해서 셀수있다는 것입니다.

이를 방지하기 위해서 좌측에서 우측으로 상단에서 하단으로 순서대로 탐색합니다.

탐색중 빈칸을 만나면 블록의 각 모양을 대입하고 놓을수 있으면 놓고 재귀호출합니다.

이문제의 까다로운 점은 L자 모양의 블록을 90도 돌려가면서 나올수 있는 여러가지 모양의 블록을 두개의 2차원배열로 표현하여 하나씩 대입해봐야 된다는 겁니다.

하지만 경우의 수가 4가지 밖에 안되기때문에 충분히 수동으로 입력가능합니다.

 

 

#include<iostream>
#include<cstring>
using namespace std;
int H, W;
// 90도씩 돌려가며 각각의 블럭을 표현
int dx[4][3] = {
{0, 0, 1},
{0, 0, 1},
{0, 1, 1},
{-1, 0, 0}
};
int dy[4][3] = {
{0, 1, 1},
{0, 1, 0},
{0, 0, 1},
{1, 0, 1}
};
char board[21][21];
bool inRange(int x, int y) {
if (x < 0 || x >= W)
return false;
if (y < 0 || y >= H)
return false;
return true;
}
int coverNumber() {
int x, y;
int ret = 0;
x = y = -1;
//빈칸 찾는중...
for (int i = 0; i < H; i++) {
for (int j = 0; j < W; j++)
if (board[i][j] == '.') {
x = j; y = i;
break;
}
if (x != -1)break;
}
//빈칸이 없으면 return 1;
if (x == -1) return 1;
//90도로 돌려가며 퍼즐을 하나씩 맞춰본다
for (int i = 0; i < 4; i++) {
int can = true;
for (int j = 0; j < 3; j++) {
int cx = x + dx[i][j];
int cy = y + dy[i][j];
if (!inRange(cx, cy) || board[cy][cx] == '#')
can = false;
}
// 퍼즐이 알맞게 들어간다면
if (can) {
for (int j = 0; j < 3; j++) {
int cx = x + dx[i][j];
int cy = y + dy[i][j];
board[cy][cx] = '#';
}
ret += coverNumber();
for (int j = 0; j < 3; j++) {
int cx = x + dx[i][j];
int cy = y + dy[i][j];
board[cy][cx] = '.';
}
}
}
return ret;
}
int main() {
int testcase;
cin >> testcase;
while (testcase--) {
cin >> H >> W;
memset(board, 0, sizeof(board));
for (int i = 0; i < H; i++)
cin >> board[i];
cout << coverNumber() << endl;
}
}

코드 원본: https://github.com/sbl133/JongmanBook/blob/main/6.%20brute-force/BOARDCOVER.cpp

 

GitHub - sbl133/JongmanBook

Contribute to sbl133/JongmanBook development by creating an account on GitHub.

github.com

댓글을 통한 코드리뷰, 질문, 지적 언제든 환영입니다!

reference: 프로그래밍 대회에서 배우는 알고리즘 문제해결전략1

algospot 문제 링크 : https://www.algospot.com/judge/problem/read/PICNIC

 

algospot.com :: PICNIC

소풍 문제 정보 문제 안드로메다 유치원 익스프레스반에서는 다음 주에 율동공원으로 소풍을 갑니다. 원석 선생님은 소풍 때 학생들을 두 명씩 짝을 지어 행동하게 하려고 합니다. 그런데 서로

www.algospot.com

입력으로 학생수와 친구쌍이 주어졌을때 친구쌍으로만 짝꿍을 만들수 있는 경우의 수를 구하는문제입니다.

재귀호출을 이용해 완전탐색으로 문제를 풀 수 있습니다.

이때 주의할점은 실질적으로 같은 답을 중복으로 세는 경우가 있을수 있다는 것입니다.

예를들어 0,1과 2,3 이 각각 친구일때 (2,3), (0,1) or (1,0), (2,3) or (0,1), (2,3)등을 중복해서 셀수 있습니다.

이를 방지하기 위해서는 각 단계에서 남아 잇는 학생들 중 가장 번호가 빠른 학생의 짝을 먼저 찾아 주면 됩니다.

 

#include<iostream>
#include<vector>
#include<cstring>
using namespace std;
// 학생수
int n;
// 친구를 나타내는 2차원배열
bool areFriends[10][10];
int countPairings(bool taken[10]) {
// 짝궁이 안정해진 맨 앞번호
int firstFree = -1;
int ret = 0;
for (int i = 0; i < n; i++)
if (taken[i] == false) {
firstFree = i;
break;
}
if (firstFree == -1) return 1;
for (int pairWith = firstFree + 1; pairWith < n; pairWith++) {
if (taken[pairWith] == false && areFriends[firstFree][pairWith]) {
taken[firstFree] = taken[pairWith] = true;
ret += countPairings(taken);
taken[firstFree] = taken[pairWith] = false;
}
}
return ret;
}
int main() {
int testcase;
cin >> testcase;
while (testcase--) {
int numberOfPair;
int x, y;
bool taken[10];
memset(taken, 0, sizeof(taken));
memset(areFriends, 0, sizeof(areFriends));
cin >> n >> numberOfPair;
for (int i = 0; i < numberOfPair; i++) {
cin >> x >> y;
areFriends[x][y] = true;
areFriends[y][x] = true;
}
cout << countPairings(taken) << endl;
}
}

코드 원본: https://github.com/sbl133/JongmanBook/blob/main/6.%20brute-force/PICNIC.cpp

 

GitHub - sbl133/JongmanBook

Contribute to sbl133/JongmanBook development by creating an account on GitHub.

github.com

댓글을 통한 코드리뷰, 질문, 지적 언제든 환영입니다!

reference: 프로그래밍 대회에서 배우는 알고리즘 문제해결전략1

+ Recent posts