-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.cpp
164 lines (152 loc) · 5 KB
/
main.cpp
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
/*
L'input représente une carte topographique avec des altitudes. Chaque point sur la carte est caractérisé par une lettre de 'a' (le point le plus bas) à 'z' (le point le plus élevé).
Dans la première partie, l'objectif est de déterminer le chemin le plus court pour se rendre du point "S" (qui a une altitude de 'a') au point "E" (qui a une altitude de 'z')
en utilisant le moins d'étapes possible. Les déplacements sur la carte sont soumis à des contraintes d'altitude spécifiques :
on ne peut se déplacer que d'une unité d'altitude vers le haut, par exemple en passant d'une case 'a' à une case 'b'.
Cependant, il est également permis de descendre de manière continue, par exemple en passant d'une case 'z' à une case 'a'.
La réponse attendue est le nombre d'étapes minimum nécessaires pour atteindre cet objectif.
Dans la partie 2, l'objectif est de déterminer quel point de départ "S" (les cases ayant une altitude de 'a') permettra d'obtenir le chemin le plus court pour atteindre l'objectif.
Une fois le point de départ trouvé, l'algorithme renverra le nombre d'étapes minimum nécessaire pour ce point trouvé.
*/
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <queue>
#include <unordered_set>
#include <cmath>
using namespace std;
const int MAP_WIDTH = 101;
const int MAP_HEIGHT = 41;
const int INDEX_HELPER[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
struct Point
{
int y;
int x;
};
class Node
{
public:
int id; // Id unique du noeud, permettant de determiner s'il a été visité ou non
float coutG; // Le coût pour aller du point de départ à ce noeud
int elevation; // Valeur numérique de l'élévation
Point coord; // Coordonnées sur la map
vector<Node *> getChild(Node grid[MAP_HEIGHT][MAP_WIDTH]) const
{
// Récupère les childs de la node
vector<Node *> v;
for (int i = 0; i < 4; i++)
{
const int x = coord.x + INDEX_HELPER[i][0];
const int y = coord.y + INDEX_HELPER[i][1];
if (x >= 0 && x < MAP_WIDTH && y >= 0 && y < MAP_HEIGHT)
{
v.push_back(&grid[y][x]);
}
}
return v;
}
};
Node graph[MAP_HEIGHT][MAP_WIDTH];
Node *startNode;
Node *endNode;
vector<Node *> startP2;
// Fonction de recherche de chemin par BFS
int solverBFS(Node *start)
{
start->coutG = 0;
queue<Node *> queue; // Queue pour stocker les noeuds a visiter
unordered_set<int> visited; // Liste des noeuds deja visité
queue.push(start); // Ajout du noeud de départ a la queue
while (!queue.empty())
{
const Node *currentNode = queue.front(); // Récupération du premier element de la queue
queue.pop(); // Suppression du premiere element de la queue
// Si le noeud a deja été visité, on passe au suivant
if (visited.find(currentNode->id) != visited.end())
{
continue;
}
// Si le noeud est le noeud de fin, on quitte la boucle
if (currentNode == endNode)
{
break;
}
// On insert le noeud dans la liste visited
visited.insert(currentNode->id);
// On récupère les childs du noeud
vector<Node *> childs = currentNode->getChild(graph);
for (int i = 0; i < childs.size(); i++)
{
Node *child = childs[i];
int diffElevation = child->elevation - currentNode->elevation; // On calcule la différence d'élévation entre le noeud et l'enfant
// Si cette différence est <= à 1 (permet de passer à un dénivelé de 1 de hauteur en plus ou de descendre en continu)
if (diffElevation <= 1)
{
if (child->coutG > currentNode->coutG + 1)
{
child->coutG = currentNode->coutG + 1;
}
if (visited.find(child->id) == visited.end())
{
queue.push(child);
}
}
}
}
return endNode->coutG;
}
int main()
{
string filename = "input.txt";
ifstream file(filename);
if (!file.is_open())
{
cerr << "Erreur : impossible d'ouvrir le fichier " << filename;
return 1;
}
string line;
int index = 0;
// Parcourir l'input pour remplir le graph
while (getline(file, line))
{
for (int i = 0; i < MAP_WIDTH; i++)
{
char c = line[i];
graph[index][i] = Node{index * MAP_WIDTH + i, numeric_limits<float>::max(), c - 'a', {index, i}};
// Initialiser startNode
if (c == 'S')
{
startNode = &graph[index][i];
startNode->coutG = 0;
startNode->elevation = 0;
}
// Initialiser endNode
if (c == 'E')
{
endNode = &graph[index][i];
endNode->elevation = 25;
}
// Dénivelé 'a' trouvé, à mettre dans startP2
if (c == 'a')
{
startP2.push_back(&graph[index][i]);
}
}
index++;
}
file.close();
int part1 = solverBFS(startNode);
int part2 = part1;
for (int i = 0; i < startP2.size(); i++)
{
int value = solverBFS(startP2[i]);
if (value < part2)
{
part2 = value;
}
}
cout << "Part1: " << part1 << endl;
cout << "Part2: " << part2 << endl;
return 0;
}