144 lines
3.1 KiB
C++
144 lines
3.1 KiB
C++
#ifndef SIMULATED_ANNEALING_HEADER_12647_H
|
|
#define SIMULATED_ANNEALING_HEADER_12647_H
|
|
|
|
#include <algorithm>
|
|
#include <iostream>
|
|
#include <queue>
|
|
#include <random>
|
|
#include <vector>
|
|
#include <set>
|
|
|
|
namespace sa {
|
|
|
|
class solution {
|
|
std::vector<long long> items;
|
|
std::default_random_engine gen;
|
|
int capacity;
|
|
int fitness;
|
|
int iterations;
|
|
int iteration;
|
|
|
|
auto calculate_boxes()->int {
|
|
int count = 1;
|
|
long long now = 0;
|
|
|
|
for (auto i : items) {
|
|
if (now + i > capacity) {
|
|
count++;
|
|
now = i;
|
|
continue;
|
|
}
|
|
now += i;
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
static void print_box(int box, std::queue<long long> &stored) {
|
|
std::cout << "Caixa " << box << ":";
|
|
while (!stored.empty()) {
|
|
std::cout << ' ' << stored.front();
|
|
stored.pop();
|
|
}
|
|
std::cout << '\n';
|
|
}
|
|
|
|
public:
|
|
solution() = default;
|
|
|
|
solution(const solution &other, int itr): items(other.items), gen(other.gen),
|
|
capacity(other.capacity), fitness(other.fitness),
|
|
iteration(itr) {}
|
|
|
|
solution(const std::vector<long long> &items, int capacity): // Gera a solução inicial
|
|
gen(std::random_device()()), capacity(capacity),
|
|
iteration(0) {
|
|
std::multiset<long long> its;
|
|
for (auto i : items) {
|
|
its.insert(i);
|
|
}
|
|
|
|
this->items.resize(items.size());
|
|
size_t i = 0;
|
|
|
|
long long cap = capacity;
|
|
|
|
while (!its.empty()) {
|
|
auto itr = its.upper_bound(cap);
|
|
if (itr == its.begin()) {
|
|
cap = capacity;
|
|
cap -= *its.begin();
|
|
itr = its.begin();
|
|
} else {
|
|
itr--;
|
|
cap -= *itr;
|
|
}
|
|
this->items[i] = *itr;
|
|
its.erase(itr);
|
|
i++;
|
|
}
|
|
|
|
fitness = calculate_boxes();
|
|
}
|
|
|
|
void setneighbor() { // Gera um vizinho da solução
|
|
std::uniform_int_distribution<> dist(0, items.size() - 1);
|
|
int first = dist(gen);
|
|
int second = 0;
|
|
while ((second = dist(gen)) == first) {}
|
|
|
|
std::swap(items[first], items[second]);
|
|
fitness = calculate_boxes();
|
|
}
|
|
|
|
void randomize() {
|
|
std::shuffle(items.begin(), items.end(), gen);
|
|
|
|
fitness = calculate_boxes();
|
|
}
|
|
|
|
void swap(solution &other) {
|
|
std::swap(fitness, other.fitness);
|
|
std::swap(items, other.items);
|
|
std::swap(capacity, other.capacity);
|
|
std::swap(gen, other.gen);
|
|
std::swap(iteration, other.iteration);
|
|
}
|
|
|
|
void print_sol() const {
|
|
std::cout << "Iteração da solução: " << iteration << '\n';
|
|
std::cout << "Número de iterações calculadas: " << iterations << '\n';
|
|
std::cout << "Número de caixas: " << fitness << '\n';
|
|
|
|
int box_now = 1;
|
|
long long now = 0;
|
|
std::queue<long long> items_stored;
|
|
|
|
for (auto i : items) {
|
|
if (now + i > capacity) {
|
|
print_box(box_now, items_stored);
|
|
box_now++;
|
|
now = i;
|
|
} else {
|
|
now += i;
|
|
}
|
|
items_stored.push(i);
|
|
}
|
|
|
|
print_box(box_now, items_stored);
|
|
std::cout << '\n';
|
|
}
|
|
|
|
void setiterations(int itr) {
|
|
iterations = itr;
|
|
}
|
|
|
|
static auto simulated_annealing(int capacity, const std::vector<long long> &items,
|
|
double alpha, double temp,
|
|
double temp_min)->solution;
|
|
};
|
|
|
|
} // namespace sa
|
|
|
|
#endif
|