Skip to content

Commit af34595

Browse files
committed
서강 그라운드
1 parent 71181b6 commit af34595

File tree

1 file changed

+160
-0
lines changed

1 file changed

+160
-0
lines changed

challenges/BOJ14938.md

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
# 문제
2+
서강 그라운드
3+
## 문제 원본
4+
문제의 원본은 [여기서](https://www.acmicpc.net/problem/14938) 확인하세요.
5+
6+
## 분류
7+
* 플로이드 와샬
8+
9+
# 풀이
10+
11+
플로이드 와샬에서 A배열 업데이트 과정에서 최단 거리가 탐색 범위를 초과 하지 않도록 조건을 걸어준다. 그 후 A배열이 업데이트 될때 `N[i][j]`의 값을 업데이트 하는데 이 `N[i][j]`의 값은 정점 i에서 시작했을때 정점 j에서 얻는 아이템의 수이다. 결과는 N배열에서 모든 i에서 j에 대한 합이 최대가 되는 값을 출력한다.
12+
13+
``` c++
14+
#include <iostream>
15+
#include <algorithm>
16+
#include <vector>
17+
18+
#define INF 10000000
19+
20+
using namespace std;
21+
22+
23+
class Graph {
24+
public:
25+
int n;
26+
vector<pair<int, int>>* adj;
27+
int *nItems; // 정점에서 얻을 수 잇는 아이템수
28+
29+
Graph(int n) {
30+
this->n = n;
31+
adj = new vector<pair<int, int>>[n + 1];
32+
nItems = new int[n + 1];
33+
nItems[0] = 0;
34+
}
35+
36+
// 간선 추가
37+
void insertEdge(int u, int v, int w) {
38+
this->adj[u].push_back(make_pair(v, w));
39+
this->adj[v].push_back(make_pair(u, w));
40+
}
41+
42+
// 정점 v에서 얻을 수 있는 아이템 수 설정
43+
void setNItems(int v, int n) {
44+
nItems[v] = n;
45+
}
46+
};
47+
48+
void input(Graph* g, int nVertices, int nEdges) {
49+
for (int i = 1; i < nVertices + 1; i++) {
50+
int nItems;
51+
cin >> nItems;
52+
g->setNItems(i, nItems);
53+
}
54+
55+
for (int i = 0; i < nEdges; i++) {
56+
int u, v, w;
57+
cin >> u >> v >> w;
58+
59+
g->insertEdge(u, v, w);
60+
}
61+
}
62+
63+
64+
// N[i][j] : i에서 출발해 탬색 범위 내의 j에서 얻을 수 있는 아이템 수
65+
int solve(Graph* g, int range) {
66+
int** A = new int*[(g->n) + 1];
67+
int** N = new int* [(g->n) + 1];
68+
69+
for (int i = 0; i < g->n + 1; i++) {
70+
A[i] = new int[(g->n) + 1];
71+
N[i] = new int[(g->n) + 1];
72+
}
73+
74+
// 기본값 A에서 자신에 대해 0, 아닌경우는 INF로 초기화 하고
75+
for (int i = 0; i < g->n + 1; i++) {
76+
for (int j = 0; j < g->n + 1; j++) {
77+
N[i][j] = 0;
78+
if (i == j) {
79+
A[i][j] = 0;
80+
}
81+
else {
82+
A[i][j] = INF;
83+
}
84+
}
85+
}
86+
87+
// 처음 알 수 있는 인접정점에 대해 A를 업데이트 한다.
88+
for (int i = 0; i < g->n + 1; i++) {
89+
N[i][i] = g->nItems[i];
90+
91+
int s = g->adj[i].size();
92+
for (int j = 0; j < s; j++) {
93+
pair<int, int> v = g->adj[i][j];
94+
95+
// 인접 정점이 탐색 범위 내에 있는 경우만
96+
if (v.second <= range) {
97+
A[i][v.first] = v.second;
98+
N[i][v.first] = g->nItems[v.first];
99+
}
100+
}
101+
}
102+
103+
104+
// Floyd Warshall
105+
for (int k = 0; k < g->n + 1; k++) {
106+
for (int i = 0; i < g->n + 1; i++) {
107+
for (int j = 0; j < g->n + 1; j++) {
108+
int newPath = A[i][k] + A[k][j];
109+
// 새로 구해진 정점 k를 거쳐 가는 최단 거리가 탐색 범위 내인 경우만
110+
if (newPath < A[i][j] && newPath <= range) {
111+
A[i][j] = newPath; // A 업데이트
112+
N[i][j] = g->nItems[j]; // i에서 출발했을때 j에서 얻는 아이템수
113+
}
114+
}
115+
}
116+
}
117+
118+
119+
// i에서 출발한 탐색범위 내의 j에서 얻을 수 있는 아이템수를 다 더한다.
120+
// 그후 가장 많이 얻을 수 있는 아이템의 수를 찾는다.
121+
int res = -0x7fffffff;
122+
for (int i = 0; i < g->n + 1; i++) {
123+
int sum = 0;
124+
125+
// 정점 i시작 한 경우 얻을 수 있는 아이템수 합
126+
for (int j = 0; j < g->n + 1; j++) {
127+
if (N[i][j] != 0) {
128+
sum += N[i][j];
129+
}
130+
}
131+
132+
// 가장 큰 값을 찾는다.
133+
res = max(res, sum);
134+
}
135+
136+
// 결과 res
137+
return res;
138+
}
139+
140+
141+
int main(void) {
142+
ios::sync_with_stdio(false);
143+
cin.tie(0); cout.tie(0);
144+
145+
// 정점 수, 탐색 범위, 간선 수 입력
146+
int nVertices, range, nEdges;
147+
cin >> nVertices >> range >> nEdges;
148+
149+
// 그래프 생성
150+
Graph* g = new Graph(nVertices);
151+
152+
// 입력
153+
input(g, nVertices, nEdges);
154+
155+
// 결과 출력
156+
cout << solve(g, range);
157+
158+
return 0;
159+
}
160+
```

0 commit comments

Comments
 (0)