일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
Tags
- dropout
- 2023
- 플로이드 와샬
- 미래는_현재와_과거로
- 이분 탐색
- tensorflow
- 자바스크립트
- 가끔은 말로
- 조합론
- 회고록
- 우선 순위 큐
- 세그먼트 트리
- 다익스트라
- Overfitting
- 알고리즘
- 백트래킹
- dfs
- back propagation
- 가끔은_말로
- 크루스칼
- 문자열
- NEXT
- lazy propagation
- object detection
- BFS
- 너비 우선 탐색
- c++
- pytorch
- DP
- 분할 정복
Archives
- Today
- Total
Doby's Lab
[알고리즘] 백준 1507번: 궁금한 민호 (C++) 본문
https://www.acmicpc.net/problem/1507
1507번: 궁금한 민호
첫째 줄에 도시의 개수 N(1 ≤ N ≤ 20)이 주어진다. 둘째 줄부터 N개의 줄에 각각의 도시 사이에 이동하는데 필요한 시간이 주어진다. A에서 B로 가는 시간과 B에서 A로 가는 시간은 같다. 또, A와 B
www.acmicpc.net
이번 문제는 floydWarshall의 reverse였다.
>> 최단 경로가 갱신된 그래프를 반대로 초기의 상태로 만들어야 했다.
처음에는 아래 코드 (3) 번 조건에서 갱신이 되지 않은 그래프를 만드려고 graph[i][j]값에 INF를 할당했었는데
이는 최단 경로를 역 갱신하는 과정에서 오류를 발생시킨다.
INF값을 할당해버리면 그 다음 노드들을 검사했을 때, 2번 조건에 의해 종료가 되어버리는 오류가 생긴다.
>> 즉, 초기의 상태로 돌려두겠다고 그래프에 INF값을 할당하면 안 되는 문제였다.
>> 각 경로의 값을 그대로 두고, check배열을 선언하여 갱신되었던 경로라면 체크해두고, 결괏값을 구할 때,
그 경로는 무시한다.
이번 문제의 포인트는 '어떻게 갱신되었던 경로 값을 무시할 것인가'가 포인트였다.
>> 저 아이디어 자체로 보면 쉽지만 무시를 해야 하는가 갱신을 해야 하는가를 두었을 때, 어려웠던 문제다.
그리고, -1을 출력하는 조건은 이미 최단 경로들이 모두 갱신된 그래프가 주어졌기 때문에
최단 경로가 갱신되려 하면 -1을 출력해주면 되었다.
[AC 코드]
#include <iostream>
#define MAX_V 21
#define INF 987654321
using namespace std;
int n;
int graph[MAX_V][MAX_V];
bool check[MAX_V][MAX_V];
void floydWarshall(){
for(int k = 1; k <= n; k++){
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
// (1)
// ex) i = 1, k = 1, j = 2로 주어졌을 때
// 이미 graph[i][k] = 0; 이라서 헛된 check가 갱신되기
// 때문에 continue처리 시킨다.
if (i == k || k == j) continue;
// (2)
// 이미 최단 경로로 모두 갱신되어있는 그래프다.
// 새롭게 갱신이 된다는 것은 말이 안되기 때문에
// -1을 출력한다.
if (graph[i][k] + graph[k][j] < graph[i][j]) {
cout << -1;
exit(0);
}
// (3)
// 갱신했던 그래프를 찾아내어 해당 경로는 갱신이
// 되었음을 check를 통해 알려준다.
if (graph[i][k] + graph[k][j] == graph[i][j]) {
check[i][j] = true;
}
}
}
}
}
int main(){
cin >> n;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
cin >> graph[i][j];
}
}
floydWarshall();
/*
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
if(graph[i][j] == INF) cout << "INF" << ' ';
else cout << graph[i][j] << ' ';
}
cout << '\n';
}
*/
int result = 0;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
if(check[i][j]) continue;
result += graph[i][j];
}
}
result /= 2; // ex) 1 -> 2, 2 -> 1을 모두 더했기 때문에 /= 2를 해준다.
cout << result;
return 0;
}
728x90
'PS > BOJ' 카테고리의 다른 글
[알고리즘] 백준 1789번: 수들의 합 (C++) (0) | 2022.03.06 |
---|---|
[자료구조] 백준 1717번: 집합의 표현 (C++) (0) | 2022.03.06 |
[자료구조] 백준 13537번: 수열과 쿼리 1 (C++) (0) | 2022.03.03 |
[알고리즘] 백준 7469번: K번째 수 (C++) (0) | 2022.03.02 |
[알고리즘] 백준 13544번: 수열과 쿼리 3 (C++) (0) | 2022.03.02 |