Repository navigation
Expand file tree
/
Copy pathmain.cpp
More file actions
171 lines (162 loc) · 5.69 KB
/
Copy pathmain.cpp
File metadata and controls
171 lines (162 loc) · 5.69 KB
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
165
166
167
168
169
170
171
/* _
| | Mobile Robot Programming Toolkit (MRPT)
_ __ ___ _ __ _ __ | |_
| '_ ` _ \| '__| '_ \| __| https://www.mrpt.org/
| | | | | | | | |_) | |_
|_| |_| |_|_| | .__/ \__| https://github.com/MRPT/mrpt/
| |
|_|
Copyright (c) 2005-2026, Individual contributors, see AUTHORS file
See: https://www.mrpt.org/Authors - All rights reserved.
SPDX-License-Identifier: BSD-3-Clause
*/
#include <mrpt/graphs/CAStarAlgorithm.h>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
using namespace std;
using namespace mrpt::graphs;
/**
* This is a example of problem resolution using the CAStarAlgorithm template.
* Although this problem is better solved with dynamic programming, it
* illustrates
* perfectly how to inherit from that template in order to solve a problem.
*
* Let's assume a currency composed of coins whose values are 2, 7, 8 and 19.
* The problem consists of finding a minimal set of these coins whose total
* value
* equals a given amount.
*/
class CCoinDistribution
{
public:
size_t coins2{0};
size_t coins7{0};
size_t coins8{0};
size_t coins19{0};
CCoinDistribution() {}
/**
* Auxiliary function to calculate the amount of money. Not strictly
* necessary, but handy.
*/
size_t money() const { return 2 * coins2 + 7 * coins7 + 8 * coins8 + 19 * coins19; }
/**
* Implementing the == operator is mandatory, because it allows the A*
* algorithm to reject repeated solutions. Actually, the template should not
* compile if
* this operator is not present.
*/
inline bool operator==(const CCoinDistribution& mon) const
{
return (coins2 == mon.coins2) && (coins7 == mon.coins7) && (coins8 == mon.coins8) &&
(coins19 == mon.coins19);
}
};
/**
* To use the template, a class must be derived from CAStarAlgorithm<Solution
* Class>. In this case, the Solution Class is CCoinDistribution.
*/
class CAStarExample : public CAStarAlgorithm<CCoinDistribution>
{
private:
/**
* Problem goal.
*/
const size_t N;
public:
/**
* When a class derives from CAStarAlgorithm, its constructor should
* include all the data that define the specific problem.
*/
CAStarExample(size_t goal) : N(goal) {}
/**
* The following five methods must be implemented to use the algorithm:
*/
bool isSolutionEnded(const CCoinDistribution& s) override
{ // True if the solution is complete.
return s.money() == N;
}
bool isSolutionValid(const CCoinDistribution& s) override
{ // True if the solution is valid.
return s.money() <= N;
}
void generateChildren(const CCoinDistribution& s, vector<CCoinDistribution>& sols) override
{ // Get all the children of a solution.
// Complex classes might want to define a copy constructor (note how the
// vector in the following line is created by cloning this object four
// times).
sols = vector<CCoinDistribution>(4, s);
sols[0].coins2++; // Misma solución, más una moneda de 2.
sols[1].coins7++; // Misma solución, más una moneda de 7.
sols[2].coins8++; // Misma solución, más una moneda de 8...
sols[3].coins19++; // Y misma solución, más una moneda de 19.
}
double getHeuristic(const CCoinDistribution& s) override
{ // Heuristic cost of the remaining part of the solution.
// Check the documentation of CAStarAlgorithm to know which
// characteristics does this function need to comply.
return static_cast<double>(N - s.money()) / 19.0;
}
double getCost(const CCoinDistribution& s) override
{ // Known cost of the partial solution.
return static_cast<double>(s.coins2 + s.coins7 + s.coins8 + s.coins19);
}
};
/**
* Main function. Just calls the A* algorithm as many times as needed.
*/
int main([[maybe_unused]] int argc, [[maybe_unused]] char** argv)
{
for (;;)
{
char text[11];
printf("Input an integer number to solve a problem, or \"e\" to end.\n");
if (1 != scanf("%10s",
text)) // GCC warning: scanf -> return cannot be ignored!
{
printf("Please, input a positive integer.\n\n");
continue;
}
if (strlen(text) == 1 && (text[0] == 'e' || text[0] == 'E')) break;
int val = atoi(text);
if (val <= 0)
{
printf("Please, input a positive integer.\n\n");
continue;
}
// The solution objects and the problem are created...
CCoinDistribution solIni,
solFin; // Initial solution automatically initialized to (0,0,0,0).
CAStarExample prob(static_cast<size_t>(val));
switch (prob.getOptimalSolution(solIni, solFin, HUGE_VAL, 15))
{
case 0:
printf(
"No solution has been found. Either the number is too "
"small, or the time elapsed has exceeded 15 seconds.\n\n");
break;
case 1:
printf("An optimal solution has been found:\n");
printf(
"\t%u coins of 2 piastres.\n\t%u coins of 7 "
"piastres.\n\t%u coins of 8 piastres.\n\t%u coins of 19 "
"piastres.\n\n",
static_cast<unsigned>(solFin.coins2), static_cast<unsigned>(solFin.coins7),
static_cast<unsigned>(solFin.coins8), static_cast<unsigned>(solFin.coins19));
break;
case 2:
printf(
"A solution has been found, although it may not be "
"optimal:\n");
printf(
"\t%u coins of 2 piastres.\n\t%u coins of 7 "
"piastres.\n\t%u coins of 8 piastres.\n\t%u coins of 19 "
"piastres.\n\n",
static_cast<unsigned>(solFin.coins2), static_cast<unsigned>(solFin.coins7),
static_cast<unsigned>(solFin.coins8), static_cast<unsigned>(solFin.coins19));
break;
}
}
return 0;
}