-
2024-03-06PS(알고리즘 문제풀이) 관련 글/PS일지 2024. 3. 6. 22:49
-작업(2056, 백준)
ACM craft라는 문제와 똑같다. 순서가 정해져있기에 위상정렬을 떠올릴 수 있다. 기초적인 위상 정렬 문제이다. 위상 정렬에서 진입차수를 제거해갈 때, 해당 노드의 값을 갱신 시켜준다. (선행 노드가 걸리는 시간중 가장 최대 시간이 지난 후, 작업이 가능하다는 점을 생각해보자)
<소스 코드>
더보기#include <stdio.h> #include <algorithm> #include <vector> #include <queue> using namespace std; int time[10010], ans[10010], ent[10010]; vector <int> vec[10010]; int n; int main() { int i, j; scanf("%d", &n); for (i = 1; i <= n; i++) { int x, y; scanf("%d %d", &x, &y); time[i] = x; for (j = 0; j < y; j++) { int t; scanf("%d", &t); vec[i].push_back(t); ent[t]++; } } queue <int> q; for (i = 1; i <= n; i++) { if (ent[i] == 0) { q.push(i); ans[i] = time[i]; } } while (!q.empty()) { int now = q.front(); q.pop(); for (i = 0; i < vec[now].size(); i++) { int nw = vec[now][i]; ent[nw]--; if (ent[nw] == 0) { q.push(nw); } ans[nw] = max(ans[nw], ans[now] + time[nw]); } } int res = -2e9; for (i = 1; i <= n; i++) res = max(res, ans[i]); printf("%d", res); return 0; }
-음악프로그램(2623, 백준)
순서를 결정해야 되는 문제이다. 우선순위를 갖는 여러 그래프를 갖고 새로운 우선순위를 만들면된다. 새로운 우선순위에서 사이클이 발생한다면, 0을 출력하고, 아니라면 queue에서 나온 순서를 역순으로 출력해주면되는 간단한 문제이다.
<소스 코드>
더보기#include <stdio.h> #include <algorithm> #include <queue> #include <vector> using namespace std; int n, m; vector <int> vec[1010]; vector <int> rk[1010]; int ent[1010], ch[1010]; vector <int> ans; queue <int> q; int main() { int i, j; scanf("%d %d", &n, &m); for(i=0;i<m;i++) { int x; scanf("%d", &x); for(j=0;j<x;j++) { int y; scanf("%d", &y); rk[i].push_back(y); } } for(i=0;i<m;i++) { for(j=0;j<rk[i].size();j++) { for(int l = 0;l<j;l++) { vec[rk[i][j]].push_back(rk[i][l]); ent[rk[i][l]]++; } } } for(i=1;i<=n;i++) if(ent[i] == 0) q.push(i); while(!q.empty()) { int now = q.front(); ch[now] = 1; ans.push_back(now); q.pop(); for(i=0;i<vec[now].size();i++) { int nw = vec[now][i]; ent[nw]--; if(ent[nw] == 0) q.push(nw); } } for(i=1;i<=n;i++) { if(ch[i] == 0) { printf("0"); return 0; } } for(i=ans.size()-1;i>=0;i--) printf("%d\n", ans[i]); return 0; }
-최소비용 구하기 2(11779, 백준)
간단한 최소경로 탐색 문제이다. n과 m범위가 크기에 Dijkstra를 돌려 풀어줬다.
<소스 코드>
더보기#include <stdio.h> #include <algorithm> #include <vector> #include <queue> using namespace std; int n, m; vector<pair<int, int>> vec[1010]; int dis[1010]; int s, e; int way[1010]; vector <int> ans; void Dijkstra(int x) { int i, j; priority_queue <pair<int, int>> pq; dis[x] = 0; pq.push({0, x}); while(!pq.empty()) { int now_idx = pq.top().second, now_val = -pq.top().first; pq.pop(); if(dis[now_idx] < now_val) continue; for(i=0;i<vec[now_idx].size();i++) { int idx = vec[now_idx][i].first, val = now_val + vec[now_idx][i].second; if(dis[idx] > val) { dis[idx] = val; pq.push({-val, idx}); way[idx] = now_idx; } } } } void DFS(int x) { if(x == -1) return; else { ans.push_back(x); DFS(way[x]); } } int main() { int i, j; scanf("%d %d", &n, &m); for(i=0;i<m;i++) { int x, y, z; scanf("%d %d %d", &x, &y, &z); vec[x].push_back({y, z}); } scanf("%d %d", &s, &e); for(i=1;i<=n;i++) dis[i] = 2e9; Dijkstra(s); printf("%d\n", dis[e]); way[s] = -1; DFS(e); printf("%d\n", ans.size()); for(i=ans.size() - 1;i>=0;i--) printf("%d ", ans[i]); return 0; }
-파티(1238, 백준)
다익 응용 문제이다.각 마을에서 목적지 k 노드까지의 최단거리와, k노드에서 모든 노드까지의 최단거리를 이용하여 구하면 된다. 다익을 여러번 돌려야 하기에 dis배열 초기화에 주의하자.
<소스 코드>
더보기#include <stdio.h> #include <algorithm> #include <queue> #include <vector> using namespace std; int n, m, k; int dis[1010]; vector <pair<int, int>> vec[1010]; int Dijkstra(int s, int e) { int i, j; int dis[1010]; priority_queue <pair<int, int>> pq; pq.push({0, s}); for(i=1;i<=n;i++) dis[i] = 2e9; dis[s] = 0; while(!pq.empty()) { int now_val = -pq.top().first, now_idx = pq.top().second; pq.pop(); if(dis[now_idx] < now_val) continue; for(i=0;i<vec[now_idx].size();i++) { int idx = vec[now_idx][i].first, val = now_val + vec[now_idx][i].second; if(dis[idx] > val) { dis[idx] = val; pq.push({-val, idx}); } } } return dis[e]; } int main() { int i, j; scanf("%d %d %d", &n, &m, &k); for(i=0;i<m;i++) { int x, y, z; scanf("%d %d %d", &x, &y, &z); vec[x].push_back({y, z}); } for(i=0;i<=n;i++) dis[i] = 2e9; int res = -2e9; for(i=1;i<=n;i++) { int x = Dijkstra(i, k) + Dijkstra(k, i); if(x > res) res = x; } printf("%d", res); return 0; }
-책 정리(1818, 백준)
줄 세우기라는 문제와 같은 문제였다. 문제에서 주어진 조건은 결국 몇명을 움직여 오름차순을 만드느냐 이기때문에 움직이지 않아도 되는 사람의 수를 구해 전체 사람수에서 빼주면된다. 이때 움직이지 않아도 되는 사람 수가 LIS이다.
<소스 코드>
더보기#include <stdio.h> #include <algorithm> #include <vector> using namespace std; int n, arr[200010]; int main() { int i, j; scanf("%d", &n); for(i=0;i<n;i++) scanf("%d", &arr[i]); vector<int> lis; lis.push_back(arr[0]); for(i=1;i<n;i++) { int lb = lower_bound(lis.begin(), lis.end(), arr[i]) - lis.begin(); int sz = lis.size(); if(lb >= sz) lis.push_back(arr[i]); else lis[lb] = arr[i]; } printf("%d", n - lis.size()); return 0; }
'PS(알고리즘 문제풀이) 관련 글 > PS일지' 카테고리의 다른 글
2024-03-08 (0) 2024.03.08 2024-03-07 (1) 2024.03.07 2024-03-05 (2) 2024.03.05 2024-03-04 (0) 2024.03.04 2024-03-03 (0) 2024.03.03