-작업(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 |