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 &current_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 &current_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 &current_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 &current_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计算几何

UVA 356 - Square Pegs And Round Holes

c_cpp 130.周围地区

c_cpp 200.岛屿数量

c_cpp 127.单词阶梯

c_cpp MOFSET