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

[최단 경로] 2176155 박지현 #363

Open
wants to merge 4 commits into
base: 2176155-박지현2
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
58 changes: 58 additions & 0 deletions 12_트리/필수/BOJ_15681.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#include<iostream>
#include<vector>
#include<map>

using namespace std;

/*
* 트리의 정점의 수 구하기 응용 문제
*
* 1. 루트에서 DFS를 사용하여 탐색
* 2. 각 노드를 루트로 하는 서브트리의 정점 수를 재귀적으로 벡터에 저장
* - 서브트리에 속한 정점의 개수를 저장하는 dp 배열을 1로 초기화
* - 탐색 시 현재 정점의 자식 노드만 탐색해서 현재 정점의 dp 값에 더해줌
* 3. 쿼리로 주어지는 정점의 서브트리의 정점의 개수를 dp에서 찾아서 출력
*/

void dfs(int cur, int prev, vector<vector<int>>& tree, vector<int>& dp) {

for (int i = 0; i < tree[cur].size(); i++) { // 현재 정점의 자식 노드 탐색
if (tree[cur][i] == prev) {//만약 현재 정점의 자식노드가 prev노드와 동일하다면
continue;//다음 자식 노드 탐색
}
dfs(tree[cur][i], cur,tree, dp);//현재 정점의 자식노드가 prev노드와 동일하지 않으면 그 자식노드로부터 다시 dfs
dp[cur] += dp[tree[cur][i]]; // 자식 노드의 dp값 더해주기
}

return;
}

int main() {

//속도 향상 코드
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);

// 입력
int n, r, q, u, v;//정점의 수, 루트의 번호, 쿼리의 수, 간선의 정보를 저장할 변수 선언
cin >> n >> r >> q;//값 입력

vector<vector<int>>tree(n + 1, vector<int>(0));//트리 벡터 선언

for (int i = 0; i < n - 1; i++) {//트리에 정점 넣기
cin >> u >> v;//간선의 양 끝점 u, v
tree[u].push_back(v);//트리벡터에 넣기
tree[v].push_back(u);//트리벡터에 넣기
}

// 연산
vector<int>dp(n + 1, 1); // 자신도 자신을 루트로 하는 서브트리에 포함되므로 0이 아닌 1로 dp 초기값 설정
dfs(r, 0,tree, dp);//답 구하기

// 출력
while (q--) {
cin >> u;
cout <<dp[u] << '\n';
}
}
89 changes: 89 additions & 0 deletions 12_트리/필수/BOJ_3190.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#include <iostream>
#include <queue>

using namespace std;

int board[101][101];//사과의 위치는 모두 다르며 1행1열에는 사과가 없다.
char chg[10001];//시작 시간으로부터 몇 초가 지난 후에 어느 방향으로 방향을 틀지 저장하는 배열
int exist[101][101];

int dy[4] = { 0,1,0,-1 };
int dx[4] = { 1,0,-1,0 };


int main() {

int n, k;//보드의 크가와 사과의 개수

cin >> n >> k;

int a, b;
while(k--) {
cin >> a >> b;
board[a][b] = 1;//사과가 위치한 곳에 1 표시
}

int l;//뱀의 방향 변환 횟수
cin >> l;

int x;//게임 시작시간으로부터 x초가 끝난 뒤에
char c;//c가 L이면 왼쪽 D이면 오른쪽으로 90도 방향을 회전시킨다.
while(l--) {
cin >> x >> c;
chg[x] = c;
}

queue<pair<int, int>> where;//현재 뱀이 어디에 있는지 저장
where.push({ 1,1 });//뱀은 맨 처음에 1,1에 위치
exist[1][1] = 1;
int t = 0;//시간
int dir = 0;//0,1,2,3 중 하나의 값을 가짐

while (true) {
t++;
int new_col = where.back().first + dy[dir];
int new_row = where.back().second + dx[dir];

if (new_row<1 || new_row>n || new_col<1 || new_col>n) {
break;
}
where.push({ new_col, new_row });

if (chg[t] == 'D') {//방향이 D이면
dir++;
if (dir == 4) {
dir = 0;
}
}
else if (chg[t] == 'L') {
dir--;
if (dir == -1) {
dir = 3;
}
}

if (board[new_col][new_row] == 1) {
board[new_col][new_row] = 0;
}
else {
if (exist[new_col][new_row] == 1) {
break;
}
else {
exist[where.front().first][where.front().second] = 0;
where.pop();
}
}

if (exist[new_col][new_row] == 1) {
break;
}
else {
exist[new_col][new_row] = true;
}

}
cout << t;

return 0;
}
36 changes: 36 additions & 0 deletions 12_트리/필수/BOJ_5639.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#include <iostream>

using namespace std;
//이진검색트리를 전위 순회한 결과가 주어졌을 때 이를 후위 후위 순회한 결과로 변환
int v[10000];
void sol(int start, int end){//후위 순회
if(start>=end){
return;
}


int index;
for(index=start+1;index<end;index++){
if(v[start]<v[index]){
break;
}

}
sol(start+1, index);
sol(index, end);
cout << v[start]<<'\n';
}

int main(){


int input;
int index=0;
while(cin >> input){
v[index++]=input;
}

sol(0, index);

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

const int INF=1e9+7;
int xton[1001];
vector<pair<int, int>> graph[2][1001];
vector<int> dist[2];
int n, m, x;

void dijkstra(int w){
dist[w][x]=0;

priority_queue<pair<int, int>, vector<pair<int,int>>, greater<pair<int,int>>> q;
q.push({0,x});

while(!q.empty()){
int di=q.top().first;
int curr=q.top().second;
q.pop();

if(di>dist[w][curr]){
continue;
}
for(int i=0;i<graph[w][curr].size();i++){
int next=graph[w][curr][i].second;
int next_d=di+graph[w][curr][i].first;
if(next_d<dist[w][next]){
dist[w][next]=next_d;
q.push({next_d,next});
}
}
}
}
int main(){

cin>>n>>m>>x;

fill_n(xton, 1001,INF);

for(int i=0;i<m;i++){
int s,e,t;//start, end, time
cin>>s>>e>>t;
graph[0][s].push_back({t,e});
graph[1][e].push_back({t,s});
}
dist[0].resize(n+1, INF);
dist[1].resize(n+1, INF);

dijkstra(0);
dijkstra(1);

int answer=0;
for(int j=1;j<=n;j++){
answer=max(answer,dist[0][j]+dist[1][j]);
}
cout<<answer<<'\n';



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

using namespace std;

const int SIZE = 100;//격자의 사이즈는 100*100

// 방향: 우(0), 상(1), 좌(2), 하(3)
int dy[4] = { 0, -1, 0, 1 };
int dx[4] = { 1, 0, -1, 0 };

// 1x1 정사각형 개수 계산
int cntSquares(vector<vector<bool>>& plane) {
int ans = 0;//정사각형 개수 저장할 변수 선언 초기화
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
if (plane[i][j] && plane[i + 1][j] && plane[i][j + 1] && plane[i + 1][j + 1]) {
//각각의 좌표에 대하여 현재 위치의 위, 오른쪽, 대각선방향에 값이 존재하면
ans++;//네 꼭짓점이 모두 드래곤 커브의 일부인 것의 개수 하나 증가
}
}
}
return ans;//정사각형 개수 반환
}

// 평면에 드래곤 커브를 표시
void drawDragonCurve(vector<vector<bool>>& plane, int x, int y, int d, int g) {
vector<int> direct; // 방향 저장
plane[y][x] = plane[y + dy[d]][x + dx[d]] = true; // 평면에 표시 (초기화)
x += dx[d];//방향 새로 설정
y += dy[d];//방향 새로 설정
direct.push_back(d);//인자로 받아온 방향을 벡터에 저장
while (g--) { // 1 ~ g 세대
int size_d = direct.size();//방향 모음 벡터에 저장된 총 방향의 개수를 변수에 저장
for (int j = size_d - 1; j >= 0; j--) { // 방향 계산
int next_d = (direct[j] + 1) % 4;//다음 방향
x += dx[next_d];//방향 새로 설정
y += dy[next_d];//방향 새로 설정
plane[y][x] = true; // 평면에 표시
direct.push_back(next_d);//새 방향 벡터에 저장
}
}
}

/*
* 규칙
* 0 세대: 0
* 1 세대: 0 1
* 2 세대: 0 1 2 1
* 3 세대: 0 1 2 1 2 3 2 1
* ...
* N 세대: concat((N-1세대), ((N-1세대 거꾸로) + 1)%4)
* 평면(좌측 상단이 (0, 0))에 드래곤 커브를 그린 후 정사각형의 개수를 계산
* 드래곤 커브는 평면 밖으로 나가지 않음으로 범위를 확인할 필요 없음
* 1. 0 세대의 드래곤 커브를 먼저 저장 (초기 조건)
* 2. 세대를 거듭하면서 드래곤 커브를 그림 (규칙을 파악하는 것이 중요)
* 3. 드래곤 커브가 그려진 평면 상의 정사각형의 개수 계산 (네 꼭짓점 확인)
*/

int main()
{
int n, x, y, d, g;
vector<vector<bool>> plane(SIZE + 1, vector<bool>(SIZE + 1, false)); // 평면
// 입력
cin >> n;
// 연산 & 출력
while (n--) { // n개의 드래곤 커브 그리기
cin >> x >> y >> d >> g;//드래곤커프 시작점, 시작방향, 세대 입력
drawDragonCurve(plane, x, y, d, g);//드래곤커브 실행
}
cout << cntSquares(plane) << '\n';//1*1인 정사각형의 네 꼭짓점이 모두 드래곤 커브의 일부인 것의 개수를 출력한다.
return 0;
}
54 changes: 54 additions & 0 deletions 13_최단 경로/필수/BOJ_2458.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#include <iostream>

using namespace std;
const int INF=1000000;
const int MAX=502;

int v[MAX][MAX];

void sol(int n){//학생수를 인자로 가진다
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
for(int k=1;k<=n;k++){
if(v[j][k]>v[j][i]+v[i][k]){
v[j][k]=v[j][i]+v[i][k];
}
}
}
}
}

int main(){
int n, m;

cin >> n >> m;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
v[i][j]=INF;
}
}

for(int i=0;i<m;i++){
int a, b;//a가 작은 학생 b가 큰 학생
cin >> a >>b;
v[a][b]=1;
}

sol(n);

int answer=0;

for(int i=1;i<=n;i++){
int count=0;
for(int j=1;j<=n;j++){
if(v[i][j]!=INF || v[j][i]!=INF){
count++;
}
}
if(count==n-1){
answer++;
}
}
cout << answer;

}