diff --git "a/10_\354\235\264\353\266\204\355\203\220\354\203\211/10815.cpp" "b/10_\354\235\264\353\266\204\355\203\220\354\203\211/10815.cpp" new file mode 100644 index 0000000..6e68d06 --- /dev/null +++ "b/10_\354\235\264\353\266\204\355\203\220\354\203\211/10815.cpp" @@ -0,0 +1,56 @@ +#include +#include +#include + +using namespace std; + +int BinarySearch(int key, const vector &arr, int n) { + int left = 0; + int right = arr.size() - 1; + int mid ; + + while(left <= right) { + mid = (left+right)/2; + + if(arr[mid] == key) { + return 1; + } else if(arr[mid] < key) { //오른쪽으로 + left = mid + 1; + } else { //왼쪽으로 + right = mid -1; + } + } + + return 0; +} + +int main() +{ + + cin.tie(0); cout.tie(0); + ios_base::sync_with_stdio(NULL); + + int n,m,t; + vector arr; + cin >> n; + + while(n--) { + cin >> t ; + arr.push_back(t); + } + + + //이분탐색은 우선, 정렬 필수 !! + sort(arr.begin(), arr.end()); + + + cin >> m ; + + while(m--) { + + cin >> t; + cout << BinarySearch(t, arr, n) << ' '; + } + + return 0; +} \ No newline at end of file diff --git "a/10_\354\235\264\353\266\204\355\203\220\354\203\211/14500.java" "b/10_\354\235\264\353\266\204\355\203\220\354\203\211/14500.java" new file mode 100644 index 0000000..ea4fc67 --- /dev/null +++ "b/10_\354\235\264\353\266\204\355\203\220\354\203\211/14500.java" @@ -0,0 +1,80 @@ +import java.util.Scanner; + +public class Main { + static int N, M; + static int[][] board; + static int max_val; + static int[][] d = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} }; + static boolean[][] visited; + static int answer = 0; + + public static void main(String[] args) { + Scanner scanner = new Scanner(System.in); + N = scanner.nextInt(); + M = scanner.nextInt(); + board = new int[N][M]; + + for (int i = 0; i < N; i++) { + for (int j = 0; j < M; j++) { + board[i][j] = scanner.nextInt(); + } + } + + max_val = findMaxValue(board); + + d = new int[][] { {-1, 0}, {1, 0}, {0, -1}, {0, 1} }; + visited = new boolean[N][M]; + + for (int i = 0; i < N; i++) { + for (int j = 0; j < M; j++) { + visited[i][j] = true; + dfs(i, j, 1, board[i][j]); + visited[i][j] = false; + } + } + + System.out.println(answer); + } + + static void dfs(int x, int y, int step, int total) { + if (total + max_val * (4 - step) <= answer) { + return; + } + + if (step == 4) { + answer = Math.max(answer, total); + return; + } + + for (int[] direction : d) { + int nx = x + direction[0]; + int ny = y + direction[1]; + + if (isValid(nx, ny) && !visited[nx][ny]) { + if (step == 2) { + visited[nx][ny] = true; + dfs(x, y, step + 1, total + board[nx][ny]); + visited[nx][ny] = false; + } + + visited[nx][ny] = true; + dfs(nx, ny, step + 1, total + board[nx][ny]); + visited[nx][ny] = false; + } + } + } + + static boolean isValid(int x, int y) { + return x >= 0 && x < N && y >= 0 && y < M; + } + + static int findMaxValue(int[][] arr) { + int max = Integer.MIN_VALUE; + for (int[] row : arr) { + for (int val : row) { + max = Math.max(max, val); + } + } + return max; + } +} diff --git "a/10_\354\235\264\353\266\204\355\203\220\354\203\211/16401.cpp" "b/10_\354\235\264\353\266\204\355\203\220\354\203\211/16401.cpp" new file mode 100644 index 0000000..b48ddc1 --- /dev/null +++ "b/10_\354\235\264\353\266\204\355\203\220\354\203\211/16401.cpp" @@ -0,0 +1,62 @@ +#include +#include +#include //max 함수 헤더파일 + + +using namespace std; + +//이분 탐색. 반복문으로 구현. +int binarySearch(int max_snack, const vector &snack_length, int m) { + int cnt = 0; //나눠줄 수 있는 총 과자의 수 + int res = 0; + + int left = 1; + int right = max_snack; + int mid=0; + + while(left <= right) { + cnt = 0; + mid = (left+right) / 2; + + for(int i=0; i= m) { + left = mid+1; //오른쪽 이동 (더 큰 과자 사이즈로) + res = mid ; + + + } + + //나눠줄 수 있는 과자가 조카 수보다 작으면, 현재 길이로는 잘라줄 수 없음. + else { + right = mid-1; //왼쪽 이동 (더 작은 과자 사이즈로 자르기) + } + + } + + return res; +} + +int main() +{ + int m, n, t; + vector snack_length; //과자 길이들 저장할 벡터 + + cin >> m >> n; + + int max_snack = 1; //과자의 최대 길이 저장할 변수 + + //과자 길이 입력받기 + while(n--) { + cin >> t ; + snack_length.push_back(t); + max_snack = max(t, max_snack); + } + + cout << binarySearch(max_snack, snack_length, m); + + return 0; +} \ No newline at end of file diff --git "a/10_\354\235\264\353\266\204\355\203\220\354\203\211/2343.cpp" "b/10_\354\235\264\353\266\204\355\203\220\354\203\211/2343.cpp" new file mode 100644 index 0000000..f5be96b --- /dev/null +++ "b/10_\354\235\264\353\266\204\355\203\220\354\203\211/2343.cpp" @@ -0,0 +1,85 @@ +#include +#include +#include //min 함수 헤더파일 + + +using namespace std; + +//블루레이 크기의 범위로 이분 탐색. 반복문으로 구현. +int binarySearch(int left, int right, const vector &lessons, int m) { + int cnt = 0; //현재 사용한 블루레이 개수 + int res = 0; + int sum = 0; //블루레이 하나에 들어간 강의들 총 길이합 + int mid=0; + + while(left <= right) { + cnt = 0; + sum=0; + mid = (left+right) /2; //현재 블루레이의 크기 + + + + //cnt 계산 + for(int i=0; imid) { //블루레이 하나가 현재 지정한 크기(mid)를 초과했으면, + cnt++; + sum=lessons[i]; //현재 강의부터 다음 블루레이에 담기 + } else if(sum==mid) { //블루레이 하나가 딱 맞게 찼으면, + cnt++; + sum=0; //다시 빈 블루레이에 채우기 시작 ! + } + + } + + if(sum>0) { + cnt++; //마지막 블루레이 포함! + } + + + + if(cnt <= m) { //사용 가능한 블루레이 수 이하로 사용함 + res = mid; //현재 크기 답안으로 저장 ! + + //여기서 블루레이 개수를 더 줄일 수 있을까? 그럴려면 각 블루레이에 강의를 덜 담아야함. 현재 블루레이 크기보다 줄여야해 ! + right = mid-1; + + } + + else { //사용 가능한 블루레이수보다 많이 사용함 + //각 블루레이에 강의를 더 담아야함. 현재 블루레이 크기보다 늘여야해 ! + left = mid+1; + } + + + } + + return res; +} + +int main() +{ + ios::sync_with_stdio(false); + cin.tie(NULL); cout.tie(NULL); + + int m, n, t; + vector lessons; //강의 길이 벡터 + + cin >> n >> m; + + int all_lessons = 0; //모든 레슨의 길이 총 합 + int max_lessons = 0; //가장 긴 레슨 길이 + + //강의 길이 입력받기 + while(n--) { + cin >> t ; + lessons.push_back(t); + all_lessons += t; + max_lessons = max(max_lessons, t); + } + + cout << binarySearch(max_lessons, all_lessons, lessons, m); + + return 0; +} \ No newline at end of file diff --git "a/10_\354\235\264\353\266\204\355\203\220\354\203\211/3079.cpp" "b/10_\354\235\264\353\266\204\355\203\220\354\203\211/3079.cpp" new file mode 100644 index 0000000..f89f73d --- /dev/null +++ "b/10_\354\235\264\353\266\204\355\203\220\354\203\211/3079.cpp" @@ -0,0 +1,55 @@ +#include +#include +#include + +using namespace std; + +//이분 탐색 +unsigned long long binarySearch(const vector& t, unsigned long long m, unsigned long long left, unsigned long long right) { + unsigned long long res = 0; + unsigned long long mid = 0; + unsigned long long q = 0; + + while (left <= right) { + mid = (left + right) / 2; + q=0; + + for (int t : t) { + q += mid / t; + } + + if (q >= m) { //m명 다 심사함 + right = mid - 1; + res = mid; + } else { + left = mid + 1; + } + } + + return res; +} + +int main() { + + ios::sync_with_stdio(false); + cin.tie(NULL); cout.tie(NULL); + + unsigned long long n,m,temp; //자료형 주의! 아니면 시간 초과.. + + + vector t; + + //입력 + cin >> n >> m; + while(n--) { + cin >> temp; + t.push_back(temp); + } + + //이분탐색 전 정렬 필수 ! + sort(t.begin(), t.end()); + + cout << binarySearch(t, m, 0, t[0] * m); + + return 0; +} diff --git "a/11_\355\210\254\355\217\254\354\235\270\355\204\260/14503.cpp" "b/11_\355\210\254\355\217\254\354\235\270\355\204\260/14503.cpp" new file mode 100644 index 0000000..13f7028 --- /dev/null +++ "b/11_\355\210\254\355\217\254\354\235\270\355\204\260/14503.cpp" @@ -0,0 +1,86 @@ +#include +#include + +using namespace std; + +const int CLEAN = 2; //청소한 상태는 2로 저장 +int cnt = 0; //청소한 칸 개수 + +//현재 칸 기준 4가지 방향: { 북, 동, 남, 서 } +int dx[4] = { 0, 1, 0, -1 }; +int dy[4] = { -1, 0, 1, 0 }; + +int clean(int n, int m, int r, int c, int d, vector>& board) { + int cnt = 0; //청소한 칸 개수 초기화 + + while (true) { //무한 루프 + //1. + if (board[r][c] != CLEAN) { //현재 칸이 아직 청소되지 않은 경우, + cnt++; //청소한 칸 수를 늘리고, + board[r][c] = CLEAN; //현재 칸을 청소한다. + } + + bool find = false; //현재 칸의 주변 4칸 중 청소되지 않은 빈 칸이 있는가 + for (int i = 0; i < 4; i++) { //3-1. 반시계 방향으로 90º 회전 + int nd = (d - i + 3) % 4; //0->3->2->1->0->3 ... 의 순서로 돌며 계속 방향 회전함 + int nr = r + dy[nd], nc = c + dx[nd]; //바라보는 방향 기준, 한 칸 전진한 값 + + if (board[nr][nc] == 0) { //3-2. + find = true; //아직 청소되지 않은 빈 칸 발견 + r = nr; c = nc; d = nd; //전진 + break; + } + } + if (find) { //3. 현재 칸의 주변 4칸 중 청소되지 않은 빈 칸이 있는 경우 1번으로 돌아감 + continue; + } + + //2. 현재 칸의 주변 4칸 중 청소되지 않은 빈 칸이 없는 경우 + int bd = (d + 2) % 4; //방향 180도 전환해서 + int br = r + dy[bd], bc = c + dx[bd]; //전진 좌표 저장 (즉, 원래 위치에서의 후진 좌표) + + //[바라보는 방향을 유지한 채로 한 칸 후진할 수 있는가] + //2-2. + if (board[br][bc] == 1) { //뒤쪽 칸이 벽이라 후진할 수 없는 경우 + return cnt; // 종료. 무한루프 탈출 + } + + //2-1. 바라보는 방향을 유지한 채로 한 칸 후진 + r = br; c = bc; //후진 + } + return cnt; // 청소한 칸 수 리턴 +} + +/* +[로봇 청소기 작동] +1. 현재 칸이 아직 청소되지 않은 경우, 현재 칸을 청소한다. +2. 현재 칸의 주변 4칸 중 청소되지 않은 빈 칸이 없는 경우, + 2-1. 바라보는 방향을 유지한 채로 한 칸 후진할 수 있다면 한 칸 후진하고 1번으로 돌아간다. + 2-2. 바라보는 방향의 뒤쪽 칸이 벽이라 후진할 수 없다면 작동을 멈춘다. +3. 현재 칸의 주변 4칸 중 청소되지 않은 빈 칸이 있는 경우, + 3-1. 반시계 방향으로 90º 회전한다. + 3-2. 바라보는 방향을 기준으로 앞쪽 칸이 청소되지 않은 빈 칸인 경우 한 칸 전진한다. + 3-3. 1번으로 돌아간다. +*/ + +int main() { + ios::sync_with_stdio(false); + cin.tie(NULL); cout.tie(NULL); + + //입력 + int n, m, r, c, d; //방 크기, 로봇 청소기 정보 + cin >> n >> m; + cin >> r >> c >> d; + + vector> board(n, vector(m, 0)); //이차원 벡터 + for (int i = 0; i < n; i++) { + for (int j = 0; j < m; j++) { + cin >> board[i][j]; + } + } + + //연산 & 출력 + cout << clean(n, m, r, c, d, board); + + return 0; +} \ No newline at end of file diff --git "a/11_\355\210\254\355\217\254\354\235\270\355\204\260/20922.cpp" "b/11_\355\210\254\355\217\254\354\235\270\355\204\260/20922.cpp" new file mode 100644 index 0000000..cb7e1ab --- /dev/null +++ "b/11_\355\210\254\355\217\254\354\235\270\355\204\260/20922.cpp" @@ -0,0 +1,68 @@ +#include +#include +#include + +using namespace std; + +int findLength(const vector &sequence, int * cnt, int k) { + + int lp=0; //시작 포인터 + int rp=0; //끝 포인터 + + int left = 0; + int right = 0; + + int cur_length=0; + int max_length=0; + int tag=0; + + while(rp> n >> k; + + vector sequence; //전체 수열 입력받을 벡터 + int cnt[200001]; //부분 수열 내 숫자들 갯수 카운팅할 배열 + + while(n--) { + cin >> t; + sequence.push_back(t); + } + + cout< +#include +#include + +using namespace std; + +int solution(const vector &dish, int *visited, int k, int c, int n) { + + //최대, 현재의 최대한 다양하게 먹은 생선의 가짓수 저장할 변수 + int max_cnt=0; + int cur_cnt=0; + + int lp=0; + int rp=0; + int left=0; + int right=0; + + int coupon = 0; // 쿠폰 적용 여부 표시 + + while ( rp-lp < k ) { //k개 이하로 먹었을 때, 초반 세팅. + + right = dish[rp]; + visited[right]++; + + if(visited[right] == 1) { //새로운 초밥이 추가되었다면, 가짓수 +1 + cur_cnt++; + } + + + if(rp-lp == k-1 ) { // k개의 초밥이 충족됐으면, 현재의 cnt 값을 max에 저장 + max_cnt = cur_cnt; + break; + } + + rp++; + + } + + + do { //딱 k개만큼 연속해서 다 먹었을 때, + + // 포인터 조정 전, 지난 lp값 제외 + left = dish[lp%n]; + visited[left]--; + if(visited[left] == 0) { //딱 하나뿐인 초밥이 빠졌다면, 가짓수 -1 + cur_cnt--; + } + + // 포인터 조정, lp부터 rp까지 새로운 k개의 초밥 + lp++; + rp++; + lp%=n; + rp%=n; + + // 회전 초밥이니깐, 원형큐의 개념 떠올리며 mod 연산해주기 + + + //rp 조정 + right = dish[rp%n]; + visited[right]++; + if(visited[right] == 1) { //새로운 초밥이 추가되었다면, 가짓수 +1 + cur_cnt++; + } + + //쿠폰 초밥 구간 내 미포함이면, 쿠폰 한 종류 더 추가 ! + if(visited[c]==0) { + cur_cnt++; + coupon=1; + } + + + + + max_cnt = max(cur_cnt, max_cnt); + + + if(coupon==1) { //쿠폰 적용 되어있으면, 초기화 ! + coupon=0; + cur_cnt--; + } + + } while( lp !=0 ); + + return max_cnt; + +} + +int main() +{ + ios::sync_with_stdio(false); + cin.tie(NULL); cout.tie(NULL); + + int n, d, k, c, t; + cin >> n >> d >> k >> c ; //접시 개수, 초밥 가짓수, 이벤트 연속 횟수, 쿠폰 초밥 + vector dish; //n개의 접시에 담긴 초밥들 저장 + int visited[d+1] = {0}; //초밥 중복 여부 체크 위한 배열 + + int x = n; + while(x--) { + cin >> t; + dish.push_back(t); + } + + cout << solution(dish, visited, k, c, n); + + return 0; +} \ No newline at end of file diff --git "a/12_\355\212\270\353\246\254/15681.cpp" "b/12_\355\212\270\353\246\254/15681.cpp" new file mode 100644 index 0000000..e4b29f2 --- /dev/null +++ "b/12_\355\212\270\353\246\254/15681.cpp" @@ -0,0 +1,58 @@ +#include +#include +using namespace std; + +vector> list, tree; // 각 노드의 연결 정보 및 트리 구조를 담을 벡터 +vector parent, subtree_size; // 부모 노드 정보 및 각 노드의 서브트리 크기를 담을 벡터 + +void makeTree(int curNode, int p) { + for (int node : list[curNode]) { + if (node != p) { + tree[curNode].push_back(node); // 트리 구조 생성 + parent[node] = curNode; // 부모 노드 정보 업데이트 + makeTree(node, curNode); // 재귀적으로 서브트리 생성 + } + } +} + +void countSubtreeNodes(int curNode) { + subtree_size[curNode] = 1; // 현재 노드를 포함한 서브트리의 크기 초기화 + + for (int node : tree[curNode]) { + countSubtreeNodes(node); // 재귀적으로 서브트리의 크기 계산 + subtree_size[curNode] += subtree_size[node]; // 서브트리의 크기 누적 + } +} + +int main() { + ios::sync_with_stdio(false); // 속도 향상 + cin.tie(NULL); + cout.tie(NULL); + + int n, r, q; + cin >> n >> r >> q; // 노드 수, 루트 노드, 쿼리 수 입력 + + parent.resize(n + 1); // 부모 노드 벡터 크기 할당 + subtree_size.resize(n + 1); // 서브트리 크기 벡터 크기 할당 + list.resize(n + 1); // 연결 정보 벡터 크기 할당 + tree.resize(n + 1); // 트리 구조 벡터 크기 할당 + + for (int i = 1; i < n; i++) { + int u, v; + cin >> u >> v; // 노드 간 연결 정보 입력 + list[u].push_back(v); + list[v].push_back(u); + } + + makeTree(r, -1); // 트리 구성 + countSubtreeNodes(r); // 각 노드의 서브트리 크기 계산 + + int query; + + while (q-- ) { + cin >> query; // 쿼리 입력 + cout << subtree_size[query] << "\n"; // 결과 출력 + } + + return 0; +} diff --git "a/12_\355\212\270\353\246\254/3190.cpp" "b/12_\355\212\270\353\246\254/3190.cpp" new file mode 100644 index 0000000..276bd25 --- /dev/null +++ "b/12_\355\212\270\353\246\254/3190.cpp" @@ -0,0 +1,75 @@ +#include +#include +#include + +using namespace std; + +int main() { + int n, k, l; + cin >> n >> k; // 보드 크기와 사과 개수 입력 + + vector> board(n, vector(n, 0)); // 맵 초기화 (0: 빈 곳, 1: 사과, 2: 뱀) + board[0][0] = 2; // 뱀의 시작 위치 + + for (int i = 0; i < k; ++i) { + int x, y; + cin >> x >> y; + board[x - 1][y - 1] = 1; // 사과의 위치 표시 + } + + cin >> l; // 방향 변환 횟수 입력 + deque> directions; // 방향 변환 정보를 담을 deque + + for (int i = 0; i < l; ++i) { + int x; + char c; + cin >> x >> c; + directions.push_back({x, c}); // 시간과 방향 정보 저장 + } + + int game_time = 0; // 게임 진행 시간 + int head_x = 0, head_y = 0; // 뱀 머리의 좌표 + int dir = 0; // 초기 방향 (오른쪽) + + int dx[] = {0, 1, 0, -1}; // 우, 하, 좌, 상 + int dy[] = {1, 0, -1, 0}; + + deque> snake; // 뱀 몸통 좌표를 담을 deque + snake.push_front({0, 0}); // 뱀 머리 추가 + + while (true) { + game_time++; // 게임 시간 증가 + + // 다음 칸으로 이동 + head_x += dx[dir]; + head_y += dy[dir]; + + // 게임 종료 조건 확인 + if (head_x < 0 || head_y < 0 || head_x >= n || head_y >= n || board[head_x][head_y] == 2) { + cout << game_time << endl; // 게임 종료 시간 출력 + break; + } + + if (board[head_x][head_y] != 1) { // 사과를 먹지 않았으면 + int tail_x = snake.back().first; + int tail_y = snake.back().second; + board[tail_x][tail_y] = 0; // 꼬리 위치 업데이트 + snake.pop_back(); // 꼬리 줄임 + } + + board[head_x][head_y] = 2; // 머리 위치 업데이트 + snake.push_front({head_x, head_y}); // 머리 추가 + + // 방향 전환 + if (!directions.empty() && directions.front().first == game_time) { + if (directions.front().second == 'L') { + dir = (dir + 3) % 4; // 왼쪽으로 방향 전환 + } else { + dir = (dir + 1) % 4; // 오른쪽으로 방향 전환 + } + directions.pop_front(); // 방향 전환 정보 삭제 + } + } + + return 0; +} diff --git "a/12_\355\212\270\353\246\254/5639.cpp" "b/12_\355\212\270\353\246\254/5639.cpp" new file mode 100644 index 0000000..24bf414 --- /dev/null +++ "b/12_\355\212\270\353\246\254/5639.cpp" @@ -0,0 +1,57 @@ +#include +#include + +using namespace std; + +// 이진 검색 트리에서 후위 순회 수행하는 함수 +void postOrder(int left, int right, vector& tree) { + if (left > right) { + return; // 왼쪽 인덱스가 오른쪽 인덱스를 초과하면 반환 (재귀의 기본 케이스) + } + + int root = tree[left]; // 이해하기 쉽게 루트 따로 저장! + + // 루트보다 큰 첫 번째 노드의 인덱스 찾기하여 새로운 left, right새로 설정 + int tmp = left + 1; + for (int i = left + 1; i <= right; i++) { + if (tree[i] > root) { // 루트보다 큰 값이 나타나면, 저장 후 break; + tmp = i; + break; + } + } + + // 후위 순회로 왼쪽 노드(루트보다 작은 값) 재귀 탐색 + postOrder(left + 1, tmp - 1, tree); + + // 후위 순회로 오른쪽 노드(루트보다 큰 값) 재귀 탐색 + postOrder(tmp, right, tree); + + // 왼쪽, 오른쪽 노드 탐색 후 루트 출력 + cout << root << '\n'; +} + +/* +* 이진 검색 트리: 루트의 왼쪽에 있는 트리 +* 이진 검색 트리의 전위 순회 결과를 후위 순회 결과로 변환 +* 전위 순회: 루트 왼쪽 오른쪽 -> 후위 순회: 왼쪽 오른쪽 루트 +* -> 탐색 결과: 루트 -> 루트보다 작은 노드(왼쪽) -> 루트보다 큰 노드(오른쪽) +* -> 루트를 기준으로 왼쪽과 오른쪽을 나누어 후위 순회로 재귀 탐색 +*/ + +// 메인 함수 +int main() { + + ios::sync_with_stdio(false); // 속도 향상 코드 + cin.tie(0); + cout.tie(0); + + // 입력 + int num; + vector tree; + while (cin >> num) { + tree.push_back(num); // 전위 순회 결과를 입력받아 tree 벡터에 저장 + } + + // 연산 후 출력. 함수 호출 + postOrder(0, tree.size() - 1, tree); +} \ No newline at end of file diff --git "a/13_\354\265\234\353\213\250\352\262\275\353\241\234/1238.cpp" "b/13_\354\265\234\353\213\250\352\262\275\353\241\234/1238.cpp" new file mode 100644 index 0000000..5cfa7e4 --- /dev/null +++ "b/13_\354\265\234\353\213\250\352\262\275\353\241\234/1238.cpp" @@ -0,0 +1,73 @@ +#include +#include +#include +#include + +using namespace std; +typedef pair ci; +const int INF = numeric_limits::max(); // 무한대 + +// 다익스트라 +vector dijkstra(int start, int v, vector>& graph) { + vector dist(v + 1, INF); // 각 정점까지의 최단 거리 + priority_queue, greater> pq; + + int weight, node, next_node, next_weight; + + dist[start] = 0; + pq.push({0, start}); // 시작. 우선순위 큐 + while (!pq.empty()) { + weight = pq.top().first; // 현재까지의 경로값 + node = pq.top().second; // 탐색 + pq.pop(); // 탐색한 정점 제거 + + if (weight > dist[node]) continue; // 최단거리 아니면, 건너뛰기 ! + + for (int i = 0; i < graph[node].size(); i++) { + next_node = graph[node][i].first; // 연결된 정점 + next_weight = weight + graph[node][i].second; // 경로값 + + // 최단거리 갱신하고 큐에 삽입 + if (next_weight < dist[next_node]) { + dist[next_node] = next_weight; + pq.push({next_weight, next_node}); + } + } + } + return dist; // 벡터를 반환함. +} + +int main() { + int n, m, x; + cin >> n >> m >> x; // 정점의 개수, 간선의 개수, 파티 장소 + + vector> graph(n + 1, vector()); // 인접 리스트 + while (m--) { + int a, b, t; + cin >> a >> b >> t; + graph[a].push_back({b, t}); // 간선 정보 + } + + vector from = dijkstra(x, n, graph); // 파티 장소부터 ~ + vector> reverse(n + 1, vector()); + + // 간선 방향 뒤집기 + for (int i = 1; i <= n; ++i) { + for (auto edge : graph[i]) { + reverse[edge.first].push_back({i, edge.second}); + } + } + vector to = dijkstra(x, n, reverse); // ~ 파티 장소까지 + + int max_time =0; + int total = 0; + + for (int i = 1; i <= n; ++i) { + total = from[i] + to[i]; // 파티까지 가는데 걸리는 토탈 시간 + max_time = max(max_time, total); + } + + cout << max_time << '\n'; + + return 0; +} diff --git "a/13_\354\265\234\353\213\250\352\262\275\353\241\234/15685.cpp" "b/13_\354\265\234\353\213\250\352\262\275\353\241\234/15685.cpp" new file mode 100644 index 0000000..ed402c9 --- /dev/null +++ "b/13_\354\265\234\353\213\250\352\262\275\353\241\234/15685.cpp" @@ -0,0 +1,87 @@ + #include +#include + +using namespace std; + +const int MAX_SIZE = 100; //맵은 최대 100,100 +bool visited [MAX_SIZE+1][MAX_SIZE+1]={false,}; +int dx[4] = {1, 0, -1, 0}; +int dy[4] = {0, -1, 0, 1}; + +//드래곤 커브 그려서, 맵에 지나간 꼭짓점 표시 +void drowCurve(int x, int y, int d, int g) { + + int cur_size=0; //현재의 벡터 사이즈 + int cx=x; //커브의 가장 마지막 점 + int cy=y; + vector curve; + visited[y][x]=true; + curve.push_back(d); + int tag = 0; + + if(g==0) { + + cx+=dx[curve[cur_size]]; + cy+=dy[curve[cur_size]]; //위치 이동! + + visited[cy][cx]=true; + + return; + } + + while(g--) { + + cur_size = curve.size()-1; + + // 해당 세대에 추가된 드래곤 커브의 방향 추가 + for(int i=cur_size; i>=0; i--) { + curve.push_back((curve[i]+1)%4); //드래곤 커브 방향 벡터에 넣기 + } + + + if(tag==0) { + cx+=dx[curve[cur_size]]; + cy+=dy[curve[cur_size]]; //위치 이동! + + visited[cy][cx]=true; + tag = 1; + } + + + // 방문한 꼭짓점 표시 + for(int i=cur_size+1; i> n; + + + + while(n--) { + cin >> x >> y >> d >> g; + drowCurve(x,y,d,g); + } + + for(int i=0; i +#include +#include + +using namespace std; +const int INF = 501; // 최대 n-1개의 간선을 지나므로 n * (가중치 최대값) + +void init(int n, vector>& graph) { + for (int i = 1; i <= n; i++) { + for (int j = 1; j <= n; j++) { + graph[i][j] = INF; // 그래스 INF 값으로 초기화 + } + } + for (int i = 1; i <= n; i++) { + graph[i][i] = 0; // 주대각선은 0으로 초기화 + } +} + +// 플로이드-워셜 +void floydWarshall(int n, vector>& graph) { + for (int k = 1; k <= n; k++) { // 중간 정점 + for (int i = 1; i <= n; i++) { // 출발 정점 + for (int j = 1; j <= n; j++) { // 도착 정점 + + // 중간에 k를 거쳐서 i에서 j로 갈 때의 비용 + int cost = graph[i][k] + graph[k][j]; + + // 더 짧은 경로 선택 + graph[i][j] = min(graph[i][j], cost); + } + } + } +} + +// 키 순서 알 수 있는지 +int countStudents(int student, int n, vector>& graph) { + int i = 1, cnt = 0; + for (i = 1; i <= n; i++) { + + // 본인 제외, 그래프에서 학생과 i 간의 거리가 INF인 경우 + if (student != i && graph[student][i] == INF && graph[i][student] == INF) { + return 0; // 키 순서를 알 수 없음 + } + } + return 1; // 순서 알 수 있음 +} +/* + * 키순서 + * 내 키의 순위를 안다 <-> 내가 상대방과의 키 우열을 안다 or 상대방이 나와의 키 우열을 안다 +*/ +int main() +{ + int n, m; + int answer = 0; + vector> graph(INF, vector(INF)); + + // 입력 + cin >> n >> m; + init(n, graph); // 초기화 + while (m--) { + int a, b; cin >> a >> b; + graph[a][b] = 1; // 키 우열을 아는 두 정점의 거리를 1이라고 하자 + } + + // 연산 + floydWarshall(n, graph); + for (int i = 1; i <= n; i++) { // 자신의 키가 몇 번째인지 알 수 있는 학생들이 몇 명인지 계산 + answer += countStudents(i, n, graph); + } + + // 출력 + cout << answer << '\n'; + return 0; +} \ No newline at end of file