Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[최단 경로] 2029011 김희진 #356

Open
wants to merge 1 commit into
base: 2029011-김희진
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 100 additions & 0 deletions 13_최단 경로/필수/BOJ_1238.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#include <iostream>
#include <vector>
#include <queue>

using namespace std;

typedef pair<int, int> ii;
const int INF = 1e5;

//start 도시부터 x까지 가는 데 걸리는 소요 시간 반환
int cityToX(int start, int n, int x, vector<vector<ii>>& graph) {
//1. start -> x 시간 계산
vector<int> time1(n + 1, INF);
priority_queue<ii, vector<ii>, greater<>> pq1; //{ 시작점으로부터의 시간, 정점 } 내림차순 정렬

//시작 정점 초기화
time1[start] = 0;
pq1.push({ 0, start });

while (!pq1.empty()) {
int time = pq1.top().first;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3. time은 다른 언어에서 키워드입니다. 혹시 모르니 주의하세요 ⚠️

int node = pq1.top().second;
pq1.pop();

//이미 저장된 시간이 새로 구한 시간보다 작을 경우 넘어감
if (time > time1[node]) {
continue;
}

for (int i = 0; i < graph[node].size(); i++) {
int next_node = graph[node][i].first;
int next_time = time + graph[node][i].second;

if (next_time < time1[next_node]) {
time1[next_node] = next_time;
pq1.push({ next_time, next_node });
}
}
}
return time1[x];
}

//x부터 각 도시까지 가는 데 걸리는 소요 시간 벡터 반환
vector<int> xToCity(int n, int x, vector<vector<ii>>& graph) {
vector<int> time2(n + 1, INF);
priority_queue<ii, vector<ii>, greater<>> pq2; //{ 시작점으로부터의 시간, 정점 } 내림차순 정렬

//시작 정점 초기화
time2[x] = 0;
pq2.push({ 0, x });

while (!pq2.empty()) {
int time = pq2.top().first;
int node = pq2.top().second;
pq2.pop();

//이미 저장된 시간이 새로 구한 시간보다 작을 경우 넘어감
if (time > time2[node]) {
continue;
}

for (int i = 0; i < graph[node].size(); i++) {
int next_node = graph[node][i].first;
int next_time = time + graph[node][i].second;

if (next_time < time2[next_node]) {
time2[next_node] = next_time;
pq2.push({ next_time, next_node });
}
}
}
return time2;
Comment on lines +43 to +72
Copy link
Contributor

@Dong-droid Dong-droid May 31, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2. dijkstra함수를 새로 만들 필요가 있을까요?? 위의 cityToX 함수를 다시 사용하는 것이 훨씬 좋습니다~

}

int main() {
ios::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);

//입력
int n, m, x, a, b, t;
cin >> n >> m >> x;

vector<vector<ii>> graph(n + 1, vector<ii>()); //graph[시작점]: { 끝점, 소요시간 }
while (m--) {
cin >> a >> b >> t;
graph[a].push_back({ b,t });
}

//연산
vector<int> time = xToCity(n, x, graph);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2. cityToX(x, n, graph)로 하면 되죠~~

int max_time = 0;
for (int i = 1; i <= n; i++) {
max_time = max(max_time, cityToX(i, n, x, graph) + time[i]);
}

//출력
cout << max_time;

return 0;
}
75 changes: 75 additions & 0 deletions 13_최단 경로/필수/BOJ_15685.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#include <iostream>
#include <vector>
#include <cmath>

using namespace std;

const int SIZE = 101;

//0: x 증가, 1: y 감소, 2: x 감소, 3: y 증가
int dx[4] = { 1,0,-1,0 };
int dy[4] = { 0,-1,0,1 };

void makeDragon(vector<int>& dragon, vector<vector<int>>& board) {
int x = dragon[0], y = dragon[1], d = dragon[2], g = dragon[3];

vector<int> dir;
dir.push_back(d); //0세대 방향

//1세대부터 방향 추가
for (int i = 0; i < g; i++) {
for (int j = pow(2, i) - 1; j >= 0; j--) {
dir.push_back((dir[j] + 1) % 4);
}
}

board[x][y] = 1; //시작 지점 표시
Copy link
Contributor

@jk0527 jk0527 May 31, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

추가로 이 문제는 격자가 정사각형이고 정사각형 개수를 세기만 하면 돼서 x, y를 어떻게 두든 상관이 없지만, 만약 격자가 직사각형이거나 좌표값이 중요한 경우 board[y][x]=1로 쓰셔야 해요!

for (int i = 0; i < dir.size(); i++) {
int nd = dir[i]; //다음 방향
int nx = x + dx[nd];
int ny = y + dy[nd];

board[nx][ny] = 1;
x = nx, y = ny;
}
}

int cntSqaure(int n, vector<vector<int>>& dragon) {
vector<vector<int>> board(SIZE, vector<int>(SIZE, 0));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

표시만 할 용도라면 boolean도 좋을 것 같네요!


//드래곤 커브 그리기
for (int i = 0; i < n; i++) {
makeDragon(dragon[i], board);
}

int cnt = 0;
for (int x = 0; x < SIZE - 1; x++) {
for (int y = 0; y < SIZE - 1; y++) {
//네 꼭짓점이 모두 드래곤 커브의 일부인 경우 횟수 증가
if (board[x][y] && board[x + 1][y] && board[x][y + 1] && board[x + 1][y + 1]) {
cnt++;
}
}
}
return cnt;
}

int main() {
ios::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);

//입력
int n, x, y, d, g;
cin >> n;

vector<vector<int>> dragon(n, vector<int>(4)); //dragon[i]: {x, y, d, g}
for (int i = 0; i < n; i++) {
cin >> x >> y >> d >> g;
dragon[i] = { x,y,d,g };
}

//연산 & 출력
cout << cntSqaure(n, dragon);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cntSquare 함수 안에서 커브를 그리고 세는 것도 좋지만, 커브를 먼저 그리고 cntSquare 함수는 이름에 맞게 세기만 하는 것도 괜찮을 것 같아요! (사소하지만 Square에 오타가 있네요..!)


return 0;
}
69 changes: 69 additions & 0 deletions 13_최단 경로/필수/BOJ_2458.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#include <iostream>
#include <vector>

using namespace std;

void floyWarshall(int n, vector<vector<int>>& graph) {
for (int k = 1; k <= n; k++) {
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
//i < k < j인 경우 i < j
if (graph[i][k] == 1 && graph[k][j] == 1) {
graph[i][j] = 1;
}

//i > k > j인 경우 i > j
if (graph[i][k] == 2 && graph[k][j] == 2) {
graph[i][j] = 2;
}
Comment on lines +15 to +18
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3. 그러면 이 부분은 필요가 없겠죠??~

}
}
}
}

int main() {
ios::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);

//입력
int n, m, a, b;
cin >> n >> m;

vector<vector<int>> graph(n + 1, vector<int>(n + 1, -1)); //graph[i][j] = 1: i가 j보다 작음, 2: i가 j보다 큼

//자기 자신과는 비교 못하므로 0으로 초기화
for (int i = 1; i <= n; i++) {
graph[i][i] = 0;
}

while (m--) {
cin >> a >> b;
graph[a][b] = 1;
graph[b][a] = 2;
Comment on lines +41 to +42
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3. 키가 작은 경우와 큰 경우를 나눌 필요는 없습니다. '키의 차이가 있다는 것을 안다'는 것만 중요하기 때문에 graph[a][b]=1;으로도 충분합니다.

}

//연산
floyWarshall(n, graph);

vector<int> cnt(n + 1, 0); //cnt[i]: i번째 학생과 비교할 수 없는 학생의 수
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (graph[i][j] == -1) {
cnt[i]++;
}
}
}

int result = 0; //자신의 키가 몇 번째인지 알 수 있는 학생의 수
for (int i = 1; i <= n; i++) {
//비교할 수 없는 학생의 수가 없는 경우에만 자신의 키 순위를 정확하게 알 수 있음
if (cnt[i] == 0) {
result++;
}
}

Comment on lines +48 to +64
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3. cnt배열을 사용하는 것도 좋은 방법입니다 👍 그런데, 함수를 사용해도 됩니다. 함수에서 자신의 키 순위를 알 수 있는 경우에 return true; 아닌 경우는 return false;를 하고 return true일 때 result++을 하면 됩니다.

//출력
cout << result;

return 0;
}