c_cpp Pegs - Copy.cpp
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c_cpp Pegs - Copy.cpp相关的知识,希望对你有一定的参考价值。
#ifndef _NDEBUG
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#endif
#include <algorithm>
#include <chrono>
#include <fstream>
#include <functional>
#include <iostream>
#include <tuple>
#include <unordered_set>
#include <vector>
struct configuration
{
std::vector<std::vector<int>> pegs;
std::tuple<size_t, size_t> move;
size_t age;
configuration()
{
}
configuration(const configuration &other)
: pegs(other.pegs), move(other.move), age(other.age)
{
}
configuration(configuration &&other)
: pegs(std::move(other.pegs)), move(std::move(other.move)), age(std::move(other.age))
{
}
configuration & operator=(const configuration &other)
{
pegs = other.pegs;
move = other.move;
age = other.age;
return *this;
}
configuration & operator=(configuration &&other)
{
pegs = std::move(other.pegs);
move = std::move(other.move);
age = std::move(other.age);
return *this;
}
};
bool operator==(const configuration &s1, const configuration &s2)
{
return s1.pegs == s2.pegs;
}
bool operator!=(const configuration &s1, const configuration &s2)
{
return s1.pegs != s2.pegs;
}
struct node
{
configuration state;
size_t cost;
node(const configuration &state)
: state(state)
{
}
node(configuration &&state)
: state(std::move(state))
{
}
node(const node &other)
: state(other.state), cost(other.cost)
{
}
node(node &&other)
: state(std::move(other.state)), cost(std::move(other.cost))
{
}
node & operator=(const node &other)
{
state = other.state;
cost = other.cost;
return *this;
}
node & operator=(node &&other)
{
state = std::move(other.state);
cost = std::move(other.cost);
return *this;
}
};
struct compare_node
{
bool operator()(const node &n1, const node &n2) const
{
return n1.cost > n2.cost;
}
};
template <typename T>
void hash_combine(std::size_t &seed, const T &v)
{
std::hash<T> hasher;
seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
template<typename It>
void hash_range(std::size_t &seed, It first, It last)
{
for (; first != last; ++first)
hash_combine(seed, *first);
}
struct hash_state
{
size_t operator()(const configuration &state) const
{
size_t result = 0;
std::for_each(state.pegs.cbegin(), state.pegs.cend(), [&result](const std::vector<int> &peg) { hash_range(result, peg.cbegin(), peg.cend()); });
return result;
}
};
struct equal_to_state
{
bool operator()(const configuration &c1, const configuration &c2) const
{
return c1 == c2;
}
};
size_t estimate_distance(const configuration ¤t_state, const configuration &final_state)
{
size_t distance = 0;
for (size_t i = 0, k = current_state.pegs.size(); i < k; i++)
{
const auto &p1 = current_state.pegs[i];
const auto &p2 = final_state.pegs[i];
size_t min, max;
std::tie(min, max) = std::minmax(p1.size(), p2.size());
for (size_t j = 0; j < min; j++)
if (p1[j] != p2[j])
distance++;
distance += max - min;
}
return distance / 2;
}
struct solver
{
configuration initial_state;
configuration final_state;
std::unordered_set<configuration, hash_state, equal_to_state> closed;
std::vector<node> fringe;
size_t expanded, generated;
solver(configuration initial_state, configuration final_state)
: initial_state(std::move(initial_state)), final_state(std::move(final_state)), expanded(), generated()
{
}
void expand(const configuration ¤t_configuration)
{
for (size_t i = 0, k = current_configuration.pegs.size(); i < k; ++i)
if (!current_configuration.pegs[i].empty())
{
auto d = current_configuration.pegs[i].back();
for (size_t j = 0; j < k; ++j)
if ((current_configuration.pegs[j].empty() || d <= current_configuration.pegs[j].back()) && i != j)
{
node new_node(current_configuration);
new_node.state.pegs[i].pop_back();
new_node.state.pegs[j].push_back(d);
generated++;
if (closed.find(new_node.state) == closed.cend())
{
new_node.cost = new_node.state.age + estimate_distance(new_node.state, final_state);
new_node.state.move = std::make_tuple(i, j);
new_node.state.age = current_configuration.age + 1;
fringe.push_back(std::move(new_node));
std::push_heap(fringe.begin(), fringe.end(), compare_node());
}
}
}
}
void print_path(configuration current) const
{
std::vector<std::tuple<size_t, size_t>> path;
while (current.age > 0)
{
auto i = std::get<0>(current.move);
auto j = std::get<1>(current.move);
path.push_back(std::move(current.move));
current.pegs[i].push_back(current.pegs[j].back());
current.pegs[j].pop_back();
current = std::move(*closed.find(current));
}
std::cout << path.size() << std::endl;
for (auto it = path.crbegin(), re = path.crend(); it != re; ++it)
std::cout << std::get<0>(*it) + 1 << ' ' << std::get<1>(*it) + 1 << std::endl;
}
void run()
{
node initial_node(initial_state);
initial_node.cost = estimate_distance(initial_state, final_state);
fringe.push_back(std::move(initial_node));
while (!fringe.empty())
{
std::pop_heap(fringe.begin(), fringe.end(), compare_node());
auto current = std::move(fringe.back().state);
fringe.pop_back();
if (current == final_state)
{
//print_path(std::move(current));
break;
}
expand(current);
expanded++;
closed.insert(std::move(current));
}
}
};
configuration read_configuration(std::istream &stream, int n, int k)
{
configuration state;
state.age = 0;
for (int i = 0; i < k; i++)
state.pegs.emplace_back();
for (int i = 0; i < n; i++)
{
int peg_number;
stream >> peg_number;
auto &peg = state.pegs[peg_number - 1];
peg.insert(peg.begin(), i + 1);
}
return state;
}
int main()
{
{
std::ifstream f("in.txt");
int n, k;
f >> n >> k;
auto initial_state = read_configuration(f, n, k);
auto final_state = read_configuration(f, n, k);
auto start = std::chrono::high_resolution_clock::now();
solver solver(std::move(initial_state), std::move(final_state));
solver.run();
auto stop = std::chrono::high_resolution_clock::now();
std::cout << std::endl << solver.generated << " nodes generated, " << solver.expanded << " nodes expanded in " << std::chrono::duration_cast<std::chrono::milliseconds>(stop - start).count() << " ms" << std::endl;
}
_CrtDumpMemoryLeaks();
}
13 3
1 1 1 1 1 1 1 1 1 1 1 1 1
2 2 2 2 2 2 2 2 2 2 2 2 2
6 4
4 2 4 3 1 1
1 1 1 1 1 1
4 3
2 2 1 3
3 3 3 3
#ifndef _NDEBUG
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#endif
#include <algorithm>
#include <chrono>
#include <fstream>
#include <functional>
#include <iostream>
#include <tuple>
#include <unordered_set>
#include <vector>
struct configuration
{
std::vector<std::vector<int>> pegs;
std::tuple<size_t, size_t> move;
size_t age;
configuration()
{
}
configuration(const configuration &other)
: pegs(other.pegs), move(other.move), age(other.age)
{
}
configuration(configuration &&other)
: pegs(std::move(other.pegs)), move(std::move(other.move)), age(std::move(other.age))
{
}
configuration & operator=(const configuration &other)
{
pegs = other.pegs;
move = other.move;
age = other.age;
return *this;
}
configuration & operator=(configuration &&other)
{
pegs = std::move(other.pegs);
move = std::move(other.move);
age = std::move(other.age);
return *this;
}
};
bool operator==(const configuration &s1, const configuration &s2)
{
return s1.pegs == s2.pegs;
}
bool operator!=(const configuration &s1, const configuration &s2)
{
return s1.pegs != s2.pegs;
}
struct node
{
configuration state;
size_t cost;
node(const configuration &state)
: state(state)
{
}
node(configuration &&state)
: state(std::move(state))
{
}
node(const node &other)
: state(other.state), cost(other.cost)
{
}
node(node &&other)
: state(std::move(other.state)), cost(std::move(other.cost))
{
}
node & operator=(const node &other)
{
state = other.state;
cost = other.cost;
return *this;
}
node & operator=(node &&other)
{
state = std::move(other.state);
cost = std::move(other.cost);
return *this;
}
};
struct compare_node
{
bool operator()(const node &n1, const node &n2) const
{
return n1.cost > n2.cost;
}
};
template <typename T>
void hash_combine(std::size_t &seed, const T &v)
{
std::hash<T> hasher;
seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
template<typename It>
void hash_range(std::size_t &seed, It first, It last)
{
for (; first != last; ++first)
hash_combine(seed, *first);
}
struct hash_state
{
size_t operator()(const configuration &state) const
{
size_t result = 0;
std::for_each(state.pegs.cbegin(), state.pegs.cend(), [&result](const std::vector<int> &peg) { hash_range(result, peg.cbegin(), peg.cend()); });
return result;
}
};
struct equal_to_state
{
bool operator()(const configuration &c1, const configuration &c2) const
{
return c1 == c2;
}
};
size_t estimate_distance(const configuration ¤t_state, const configuration &final_state)
{
size_t distance = 0;
for (size_t i = 0, k = current_state.pegs.size(); i < k; i++)
{
const auto &p1 = current_state.pegs[i];
const auto &p2 = final_state.pegs[i];
size_t min, max;
std::tie(min, max) = std::minmax(p1.size(), p2.size());
for (size_t j = 0; j < min; j++)
if (p1[j] != p2[j])
distance++;
distance += max - min;
}
return distance / 2;
}
struct solver
{
configuration initial_state;
configuration final_state;
std::unordered_set<configuration, hash_state, equal_to_state> closed;
std::vector<node> fringe;
size_t expanded, generated;
solver(configuration initial_state, configuration final_state)
: initial_state(std::move(initial_state)), final_state(std::move(final_state)), expanded(), generated()
{
}
void expand(const configuration ¤t_configuration)
{
for (size_t i = 0, k = current_configuration.pegs.size(); i < k; ++i)
if (!current_configuration.pegs[i].empty())
{
auto d = current_configuration.pegs[i].back();
for (size_t j = 0; j < k; ++j)
if ((current_configuration.pegs[j].empty() || d <= current_configuration.pegs[j].back()) && i != j)
{
node new_node(current_configuration);
new_node.state.pegs[i].pop_back();
new_node.state.pegs[j].push_back(d);
generated++;
if (closed.find(new_node.state) == closed.cend())
{
new_node.cost = new_node.state.age + estimate_distance(new_node.state, final_state);
new_node.state.move = std::make_tuple(i, j);
new_node.state.age = current_configuration.age + 1;
fringe.push_back(std::move(new_node));
std::push_heap(fringe.begin(), fringe.end(), compare_node());
}
}
}
}
void print_path(configuration current) const
{
std::vector<std::tuple<size_t, size_t>> path;
while (current.age > 0)
{
auto i = std::get<0>(current.move);
auto j = std::get<1>(current.move);
path.push_back(std::move(current.move));
current.pegs[i].push_back(current.pegs[j].back());
current.pegs[j].pop_back();
current = std::move(*closed.find(current));
}
std::cout << path.size() << std::endl;
for (auto it = path.crbegin(), re = path.crend(); it != re; ++it)
std::cout << std::get<0>(*it) + 1 << ' ' << std::get<1>(*it) + 1 << std::endl;
}
void run()
{
node initial_node(initial_state);
initial_node.cost = estimate_distance(initial_state, final_state);
fringe.push_back(std::move(initial_node));
while (!fringe.empty())
{
std::pop_heap(fringe.begin(), fringe.end(), compare_node());
auto current = std::move(fringe.back().state);
fringe.pop_back();
if (current == final_state)
{
//print_path(std::move(current));
break;
}
expand(current);
expanded++;
closed.insert(std::move(current));
}
}
};
configuration read_configuration(std::istream &stream, int n, int k)
{
configuration state;
state.age = 0;
for (int i = 0; i < k; i++)
state.pegs.emplace_back();
for (int i = 0; i < n; i++)
{
int peg_number;
stream >> peg_number;
auto &peg = state.pegs[peg_number - 1];
peg.insert(peg.begin(), i + 1);
}
return state;
}
int main()
{
{
std::ifstream f("in.txt");
int n, k;
f >> n >> k;
auto initial_state = read_configuration(f, n, k);
auto final_state = read_configuration(f, n, k);
auto start = std::chrono::high_resolution_clock::now();
solver solver(std::move(initial_state), std::move(final_state));
solver.run();
auto stop = std::chrono::high_resolution_clock::now();
std::cout << std::endl << solver.generated << " nodes generated, " << solver.expanded << " nodes expanded in " << std::chrono::duration_cast<std::chrono::milliseconds>(stop - start).count() << " ms" << std::endl;
}
_CrtDumpMemoryLeaks();
}
以上是关于c_cpp Pegs - Copy.cpp的主要内容,如果未能解决你的问题,请参考以下文章
UVA356 LA5250 Square Pegs And Round Holes计算几何