CodeReview提供的解决方案在CentOS 7.1上运行良好。我试图将其移植到Windows 7,Visual Studio 2012.通过微小的编辑,允许VS 2012不支持代码编译的C ++ 11部分,并且循环的第一次执行正常工作。测试用例的其余执行失败,每次执行时逐渐变得越来越不正确。
可以在github上找到此问题的代码。
完成计算0 / *问题这里没有问题* /
经过时间:0.202012秒
所有路径搜索的起始点是A3
所有路径搜索的目标点是H4
电路板每个边缘的方格数为8
用于进一步限制搜索的切片方法是不会重复访问任何行或列
共有5条生成路径
有323个尝试路径
平均路径长度为4.8
中值路径长度为4
最长的路径是6次移动
最短的路径是4次移动
我认为问题出现在下面列出的其中一个文件中。我已经调试了2天,我可以帮忙。
CRKnightMoves_Cpp2.cpp
/*
* KnightMoves.cpp
*
* Author: pacmaninbw
*/
#include "stdafx.h"
#include <iostream>
#include <stdexcept>
#include <chrono>
#include <ctime>
#include <algorithm>
#include <functional>
#include <vector>
#include "KnightMoves.h"
#include "KnightMovesImplementation.h"
#include "KMBoardDimensionConstants.h"
double Average(std::vector<double> TestTimes)
{
double AverageTestTime = 0.0;
double SumOfTestTimes = 0.0;
int CountOfTestTimes = 0;
for (auto TestTimesIter : TestTimes)
{
SumOfTestTimes += TestTimesIter;
CountOfTestTimes++;
}
if (CountOfTestTimes) { // Prevent division by zero.
AverageTestTime = SumOfTestTimes / static_cast<double>(CountOfTestTimes);
}
return AverageTestTime;
}
void OutputOverAllStatistics(std::vector<double> TestTimes)
{
if (TestTimes.size() < 1) {
std::cout << "No test times to run statistics on!" << std::endl;
return;
}
std::cout << std::endl << "Overall Results" << std::endl;
std::cout << "The average execution time is " << Average(TestTimes) << " seconds" << std::endl;
std::nth_element(TestTimes.begin(), TestTimes.begin() + TestTimes.size()/2, TestTimes.end());
std::cout << "The median execution time is " << TestTimes[TestTimes.size()/2] << " seconds" << std::endl;
std::nth_element(TestTimes.begin(), TestTimes.begin()+1, TestTimes.end(), std::greater<double>());
std::cout << "The longest execution time is " << TestTimes[0] << " seconds" << std::endl;
std::nth_element(TestTimes.begin(), TestTimes.begin()+1, TestTimes.end(), std::less<double>());
std::cout << "The shortest execution time is " << TestTimes[0] << " seconds" << std::endl;
}
double ExecutionLoop(KMBaseData UserInputData)
{
KnightMovesImplementation *KnightPathFinder = new KnightMovesImplementation(UserInputData);
std::chrono::time_point<std::chrono::system_clock> start, end;
start = std::chrono::system_clock::now();
KMOutputData OutputData = KnightPathFinder->CalculatePaths();
end = std::chrono::system_clock::now();
std::chrono::duration<double> elapsed_seconds = end-start;
std::time_t end_time = std::chrono::system_clock::to_time_t(end);
double ElapsedTimeForOutPut = elapsed_seconds.count();
char ctimebuffer[1024];
std::cout << "finished computation at " << ctime_s(ctimebuffer, 1024, &end_time) << "\n"
<< "elapsed time: " << ElapsedTimeForOutPut << " Seconds\n" << "\n" << "\n";
// Don't include output of results in elapsed time calculation
OutputData.DontShowPathData();
// OutputData.ShowPathData();
OutputData.ShowResults();
delete KnightPathFinder;
return ElapsedTimeForOutPut;
}
int LetUserEnterTestCaseNumber(std::vector<KMBaseData> &TestData)
{
int i = 1;
int Choice = -1;
std::cout << "Select the number of the test case you want to run.\n";
std::cout << "Test Case #" << "\tStart Name" << "\tTarget Name" << "\tBoard Size" << "\tSlicing Method" << "\n";
for (auto TestCase: TestData) {
std::cout << i << "\t" << TestCase.m_StartName << "\t" << TestCase.m_TargetName << "\t" << TestCase.m_DimensionOneSide << "\t";
switch (TestCase.m_LimitationsOnMoves)
{
default :
throw std::runtime_error("LetUserEnterTestCaseNumber : Unknown type of Path Limitation.");
case DenyByPreviousLocation :
std::cout << "Can't return to previous location";
break;
case DenyByPreviousRowOrColumn:
std::cout << "Can't return to previous row or column";
break;
}
std::cout << "\n";
i++;
}
std::cout << i << "\tAll of the above except for 13 and 14\n";
std::cout << ++i <<"\tAll of the above (Go get lunch)\n";
std::cin >> Choice;
if (Choice == 15)
{
std::vector<KMBaseData> TempTests;
for (auto TestCase: TestData)
{
if ((TestCase.m_DimensionOneSide != MaximumBoardDimension) && (TestCase.m_LimitationsOnMoves != DenyByPreviousLocation))
{
TempTests.push_back(TestCase);
}
}
TestData = TempTests;
}
return Choice;
}
void InitTestData(std::vector<KMBaseData> &TestData)
{
KMBaseData TestCases[] = {
{1,3,"A3",8,4,"H4", DefaultBoardDimensionOnOneSide, DenyByPreviousRowOrColumn},
{1,1,"A1",8,8,"H8", DefaultBoardDimensionOnOneSide, DenyByPreviousRowOrColumn},
{1,8,"A8",8,1,"H1", DefaultBoardDimensionOnOneSide, DenyByPreviousRowOrColumn},
{2,3,"B3",8,4,"H4", DefaultBoardDimensionOnOneSide, DenyByPreviousRowOrColumn},
{2,3,"B3",8,8,"H8", DefaultBoardDimensionOnOneSide, DenyByPreviousRowOrColumn},
{3,1,"C1",8,4,"H4", DefaultBoardDimensionOnOneSide, DenyByPreviousRowOrColumn},
{3,1,"A3",8,8,"H8", DefaultBoardDimensionOnOneSide, DenyByPreviousRowOrColumn},
{1,3,"A3",2,5,"B5", DefaultBoardDimensionOnOneSide, DenyByPreviousRowOrColumn}, // Minimum should be one move
{8,4,"H4",1,3,"A3", DefaultBoardDimensionOnOneSide, DenyByPreviousRowOrColumn},
{4,4,"D4",1,8,"A8", DefaultBoardDimensionOnOneSide, DenyByPreviousRowOrColumn},
{4,4,"D4",5,6,"E6", DefaultBoardDimensionOnOneSide, DenyByPreviousRowOrColumn},
{1,3,"A3",2,5,"B5", 12, DenyByPreviousRowOrColumn}, // Minimum should be one move
{1,3,"A3",2,5,"B5", DefaultBoardDimensionOnOneSide, DenyByPreviousLocation}, // Minimum should be one move
{1,3,"A3",2,5,"B5", MaximumBoardDimension, DenyByPreviousRowOrColumn} // Minimum should be one move
};
for (int i = 0; i < sizeof(TestCases)/sizeof(KMBaseData); i++) {
TestData.push_back(TestCases[i]);
}
}
int _tmain(int argc, _TCHAR* argv[])
{
int status = 0;
std::vector<KMBaseData> TestData;
std::vector<double> TestTimes;
try {
InitTestData(TestData);
int Choice = LetUserEnterTestCaseNumber(TestData);
if (Choice < 0)
{
return status;
}
if (Choice < 15)
{
ExecutionLoop(TestData[Choice-1]);
}
else
{
for (auto TestDataIter: TestData) {
TestTimes.push_back(ExecutionLoop(TestDataIter));
}
}
OutputOverAllStatistics(TestTimes);
return status;
}
catch(std::runtime_error &e) {
std::cerr << "A fatal error occurred in KnightMoves: ";
std::cerr << e.what() << std::endl;
status = 1;
}
catch(std::runtime_error *e) {
std::cerr << "A fatal error occurred in KnightMoves: ";
std::cerr << e->what() << std::endl;
status = 1;
}
catch(...) {
std::cerr << "An unknown fatal error occurred in KnightMoves." << std::endl;
status = 1;
}
return status;
}
KnightMovesImplementation.h
#pragma once
/*
* KnightMovesImplementation.h
*
* Created on: Mar 18, 2016
* Modified on: June 20, 2016
* Author: pacmaninbw
*
* This class provides the search for all the paths a Knight on a chess
* board can take from the point of origin to the destination. It
* implements a modified Knights Tour. The classic knights tour problem
* is to visit every location on the chess board without returning to a
* previous location. That is a single path for the knight. This
* implementation returns all possible paths from point a to point b.
* The actual implementation is documented in the CPP file because it
* can be changed. This head file provides the public interface which
* should not be changed. The public interface may be moved to a
* super class in the future.
*/
#ifndef KNIGHTMOVESIMPLEMENTATION_H_
#define KNIGHTMOVESIMPLEMENTATION_H_
#include "KMPath.h"
#include "KMOutputData.h"
#include "KMMoveFilters.h"
class KnightMovesImplementation {
private:
KMBoardLocation m_PointOfOrigin;
KMBoardLocation m_Destination;
unsigned int m_SingleSideBoardDimension;
KnightMovesMethodLimitations m_PathLimitations;
KMOutputData *m_Results;
KMMoveFilters *m_MoveFilters;
KMPath *m_Path;
protected:
bool CalculatePath(KMMove CurrentMove); // Recursive function
void InitPointOfOrigin(KMBaseData UserData);
void InitDestination(KMBaseData UserData);
public:
KnightMovesImplementation(KMBaseData UserData);
virtual ~KnightMovesImplementation(void);
KMOutputData CalculatePaths();
};
#endif /* KNIGHTMOVESIMPLEMENTATION_H_ */
KnightsImplementation.cpp
/*
* KnightMovesImplementation.cpp
*
* Created on: Mar 18, 2016
* Modified on: June 21, 2016
* Commented on: June 24, 2016
* Author: pacmaninbw
*
* This class implements the search for all possible paths for a Knight
* on a chess board from one particular square on the board to another
* particular square on the board.
*
* The current implementation is a Recursive Breadth First Search. Conceptually
* the algorithm implements a B+ tree with a maximum of 8 possible branches
* at each level. The root of the tree is the point of origin. A particular
* path terminates in a leaf. A leaf is the result of either reaching the
* destination, or reaching a point where there are no more branches to
* traverse.
*
* The m_Path variable is used as a stack within the search.
*
* The public interface CalculatePaths establishes the root and creates
* the first level of branching. The protected interface CalculatePath
* performs the recursive depth first search, however, the
* m_MoveFilters.GetPossibleMoves() function it calls performs a breadth
* first search of the current level.
*
*/
#include "stdafx.h"
#include "KnightMoves.h"
#include "KnightMovesImplementation.h"
#include "KMBoardDimensionConstants.h"
KnightMovesImplementation::~KnightMovesImplementation(void)
{
delete m_MoveFilters;
delete m_Results;
delete m_Path;
}
KnightMovesImplementation::KnightMovesImplementation(KMBaseData UserInputData)
: m_SingleSideBoardDimension(UserInputData.m_DimensionOneSide),
m_PathLimitations(UserInputData.m_LimitationsOnMoves)
{
InitPointOfOrigin(UserInputData);
InitDestination(UserInputData);
m_Path = new KMPath;
m_MoveFilters = new KMMoveFilters(static_cast<unsigned int>(UserInputData.m_DimensionOneSide), UserInputData.m_LimitationsOnMoves);
m_Results = new KMOutputData(m_PointOfOrigin, m_Destination, m_SingleSideBoardDimension, m_PathLimitations);
}
void KnightMovesImplementation::InitPointOfOrigin(KMBaseData UserInputData)
{
m_PointOfOrigin.SetRow(UserInputData.m_StartRow);
m_PointOfOrigin.SetColumn(UserInputData.m_StartColumn);
m_PointOfOrigin.SetName(UserInputData.m_StartName);
m_PointOfOrigin.SetBoardDimension(m_SingleSideBoardDimension);
}
void KnightMovesImplementation::InitDestination(KMBaseData UserInputData)
{
m_Destination.SetRow(UserInputData.m_TargetRow);
m_Destination.SetColumn(UserInputData.m_TargetColumn);
m_Destination.SetName(UserInputData.m_TargetName);
m_Destination.SetBoardDimension(m_SingleSideBoardDimension);
}
KMOutputData KnightMovesImplementation::CalculatePaths()
{
KMRandomAccessMoveCollection PossibleFirstMoves = m_MoveFilters->GetPossibleMoves(m_PointOfOrigin);
if (PossibleFirstMoves.empty())
{
std::cerr << "No Possible Moves in KnightMovesImplementation::CalculatePaths" << std::endl;
}
else
{
for (auto CurrentMoveIter : PossibleFirstMoves)
{
KMMove CurrentMove = CurrentMoveIter;
CurrentMove.SetOriginCalculateDestination(m_PointOfOrigin);
if (CurrentMove.IsValid()) {
CalculatePath(CurrentMove);
}
}
}
return *m_Results;
}
bool KnightMovesImplementation::CalculatePath(KMMove CurrentMove)
{
bool CompletedSearch = false;
KMBoardLocation CurrentLocation = CurrentMove.GetNextLocation();
m_Path->AddMoveToPath(CurrentMove);
m_MoveFilters->PushVisited(CurrentLocation);
if (CurrentLocation == m_Destination)
{
m_Results->AddPath(*m_Path);
CompletedSearch = true;
m_Results->IncrementAttemptedPaths();
}
else
{
if (CurrentMove.IsValid())
{
KMRandomAccessMoveCollection PossibleMoves = m_MoveFilters->GetPossibleMoves(CurrentLocation);
if (!PossibleMoves.empty())
{
for (auto NextMove : PossibleMoves)
{
CalculatePath(NextMove);
}
}
else
{
// No more moves to test, record the attempted path
m_Results->IncrementAttemptedPaths();
}
}
else
{
// There is a logic error if we get here.
std::cerr << "In KnightMovesImplementation::CalculatePath CurrentMove Not Valid" << std::endl;
}
}
m_Path->RemoveLastMove();
m_MoveFilters->PopVisited();
return CompletedSearch;
}
KMMoveFilters.h
#pragma once
/*
* KMMoveFilters.h
*
* Created on: Jun 20, 2016
* Author: pacmaninbw
*
* This class provides all the possible Knight moves for a specified location
* on the chess board. In the center of the chess board there are 8 possible
* moves. In the middle of the edge on the chess board there are 4 possible
* moves. In a corner of the chess board there are 2 possible moves. The
* location on the board provides the first filter.
* Slicing is used to allow the program to complete in a reasonable finite
* amount of time. The slicing method can be varied, the default slicing
* method is the knight can't return to any row or column it has previously
* visited. The slicing is the second filter.
*/
#ifndef KMMOVEFILTERS_H_
#define KMMOVEFILTERS_H_
#include <vector>
#include "KnightMoves.h"
#include "KMMove.h"
class KMMoveFilters {
private:
std::vector<KMBoardLocation> m_VisitedLocations;
std::vector<unsigned int> m_VisitedRows;
std::vector<unsigned int> m_VisitedColumns;
unsigned int m_SingleSideBoardDimension;
KnightMovesMethodLimitations m_PathLimitations;
static KMRandomAccessMoveCollection AllPossibleMoves;
// The 8 possible moves the knight can make.
static KMMove Left1Up2;
static KMMove Left2Up1;
static KMMove Left2Down1;
static KMMove Left1Down2;
static KMMove Right1Up2;
static KMMove Right2Up1;
static KMMove Right2Down1;
static KMMove Right1Down2;
protected:
bool IsNotPreviouslyVisited(KMMove Move) const { return IsNotPreviouslyVisited(Move.GetNextLocation()); };
bool IsNotPreviouslyVisited(KMBoardLocation Destination) const;
public:
KMMoveFilters(void);
KMMoveFilters(unsigned int BoardDimension, KnightMovesMethodLimitations SlicingMethod);
void ResetFilters(unsigned int BoardDimension, KnightMovesMethodLimitations SlicingMethod) {m_SingleSideBoardDimension = BoardDimension; m_PathLimitations = SlicingMethod; }
virtual ~KMMoveFilters(void);
void PushVisited(KMBoardLocation Location);
void PopVisited();
KMRandomAccessMoveCollection GetPossibleMoves(const KMBoardLocation CurrentLocation) const;
};
KMMoveFilters.cpp
/*
* KMMoveFilters.cpp
*
* Created on: Jun 20, 2016
* Author: pacmaninbw
*/
#include "stdafx.h"
#include <stdexcept>
#include <algorithm>
#include "KMBoardDimensionConstants.h"
#include "KMMoveFilters.h"
KMMoveFilters::~KMMoveFilters(void)
{
}
KMMoveFilters::KMMoveFilters(void)
: m_SingleSideBoardDimension(DefaultBoardDimensionOnOneSide),
m_PathLimitations(DenyByPreviousRowOrColumn)
{
AllPossibleMoves.push_back(Left1Up2);
AllPossibleMoves.push_back(Left2Up1);
AllPossibleMoves.push_back(Left2Down1);
AllPossibleMoves.push_back(Left1Down2);
AllPossibleMoves.push_back(Right1Up2);
AllPossibleMoves.push_back(Right2Up1);
AllPossibleMoves.push_back(Right2Down1);
AllPossibleMoves.push_back(Right1Down2);
}
KMMoveFilters::KMMoveFilters(unsigned int BoardDimension, KnightMovesMethodLimitations SlicingMethod)
: m_SingleSideBoardDimension(BoardDimension), m_PathLimitations(SlicingMethod)
{
AllPossibleMoves.push_back(Left1Up2);
AllPossibleMoves.push_back(Left2Up1);
AllPossibleMoves.push_back(Left2Down1);
AllPossibleMoves.push_back(Left1Down2);
AllPossibleMoves.push_back(Right1Up2);
AllPossibleMoves.push_back(Right2Up1);
AllPossibleMoves.push_back(Right2Down1);
AllPossibleMoves.push_back(Right1Down2);
}
const int Left1 = -1;
const int Left2 = -2;
const int Down1 = -1;
const int Down2 = -2;
const int Right1 = 1;
const int Right2 = 2;
const int Up1 = 1;
const int Up2 = 2;
KMMove KMMoveFilters::Left1Up2(Left1, Up2, DefaultBoardDimensionOnOneSide);
KMMove KMMoveFilters::Left2Up1(Left2, Up1, DefaultBoardDimensionOnOneSide);
KMMove KMMoveFilters::Left2Down1(Left2, Down1, DefaultBoardDimensionOnOneSide);
KMMove KMMoveFilters::Left1Down2(Left1, Down2, DefaultBoardDimensionOnOneSide);
KMMove KMMoveFilters::Right1Up2(Right1, Up2, DefaultBoardDimensionOnOneSide);
KMMove KMMoveFilters::Right2Up1(Right2, Up1, DefaultBoardDimensionOnOneSide);
KMMove KMMoveFilters::Right2Down1(Right2, Down1, DefaultBoardDimensionOnOneSide);
KMMove KMMoveFilters::Right1Down2(Right1, Down2, DefaultBoardDimensionOnOneSide);
KMRandomAccessMoveCollection KMMoveFilters::AllPossibleMoves;
KMRandomAccessMoveCollection KMMoveFilters::GetPossibleMoves(const KMBoardLocation CurrentLocation) const
{
KMRandomAccessMoveCollection PossibleMoves;
for (auto PossibeMove : AllPossibleMoves) {
KMMove *TempMove = new KMMove(PossibeMove);
TempMove->SetBoardDimension(m_SingleSideBoardDimension);
TempMove->SetOriginCalculateDestination(CurrentLocation);
if ((TempMove->IsValid()) && (IsNotPreviouslyVisited(*TempMove))) {
PossibleMoves.push_back(*TempMove);
}
}
return PossibleMoves;
}
bool KMMoveFilters::IsNotPreviouslyVisited(KMBoardLocation PossibleDestination) const
{
bool NotPrevioslyVisited = true;
if (!m_VisitedLocations.empty()) { // This is always a test, we can't move backwards
if (std::find(m_VisitedLocations.begin(), m_VisitedLocations.end(), PossibleDestination)
!= m_VisitedLocations.end()) {
NotPrevioslyVisited = false;
}
}
switch (m_PathLimitations) {
default :
throw std::runtime_error("KMPath::CheckMoveAgainstPreviousLocations : Unknown type of Path Limitation.");
case DenyByPreviousLocation :
// Always tested above.
break;
case DenyByPreviousRowOrColumn:
if ((!m_VisitedRows.empty()) && (!m_VisitedColumns.empty())) {
unsigned int PossibleRow = PossibleDestination.GetRow();
if (std::find(m_VisitedRows.begin(), m_VisitedRows.end(), PossibleRow) != m_VisitedRows.end()) {
NotPrevioslyVisited = false;
break;
}
unsigned int PossibleColum = PossibleDestination.GetColumn();
if (std::find(m_VisitedColumns.begin(), m_VisitedColumns.end(), PossibleColum) != m_VisitedColumns.end()) {
NotPrevioslyVisited = false;
}
}
break;
}
return NotPrevioslyVisited;
}
void KMMoveFilters::PushVisited(KMBoardLocation Location)
{
m_VisitedRows.push_back(Location.GetRow());
m_VisitedColumns.push_back(Location.GetColumn());
m_VisitedLocations.push_back(Location);
}
void KMMoveFilters::PopVisited()
{
m_VisitedRows.pop_back();
m_VisitedColumns.pop_back();
m_VisitedLocations.pop_back();
}
答案 0 :(得分:0)
问题是AllPossibleMoves的静态声明,GetPossibleMoves中的内存泄漏可能是问题的另一个原因。在CentOS C ++ 11版本中,AllPossibleMoves被声明为静态const,并且未在构造函数中初始化,它在外部初始化,因为它的每个成员移动都是。这不能在Visual Studio 2012 C ++中编译。由于原始版本中的执行时间原因,AllPossibleMoves被声明为静态const。
我对结果感到失望,因为这比使用用g ++编译的C ++ 11的CentOS版本慢得多。我运行它的计算机比CentOS计算机新2年,并且有8GB内存和i7处理器。
首先我展示工作代码,然后我展示程序的输出。
解决问题的最终代码是:
<强> KMMoveFilters.h 强>
#pragma once
/*
* KMMoveFilters.h
*
* Created on: Jun 20, 2016
* Author: pacmaninbw
*
* This class provides all the possible Knight moves for a specified location
* on the chess board. In the center of the chess board there are 8 possible
* moves. In the middle of the edge on the chess board there are 4 possible
* moves. In a corner of the chess board there are 2 possible moves. The
* location on the board provides the first filter.
* Slicing is used to allow the program to complete in a reasonable finite
* amount of time. The slicing method can be varied, the default slicing
* method is the knight can't return to any row or column it has previously
* visited. The slicing is the second filter.
*/
#ifndef KMMOVEFILTERS_H_
#define KMMOVEFILTERS_H_
#include <vector>
#include "KnightMoves.h"
#include "KMMove.h"
class KMMoveFilters {
private:
std::vector<KMBoardLocation> m_VisitedLocations;
std::vector<unsigned int> m_VisitedRows;
std::vector<unsigned int> m_VisitedColumns;
unsigned int m_SingleSideBoardDimension;
KnightMovesMethodLimitations m_PathLimitations;
KMRandomAccessMoveCollection AllPossibleMoves;
// The 8 possible moves the knight can make.
static KMMove Left1Up2;
static KMMove Left2Up1;
static KMMove Left2Down1;
static KMMove Left1Down2;
static KMMove Right1Up2;
static KMMove Right2Up1;
static KMMove Right2Down1;
static KMMove Right1Down2;
protected:
bool IsNotPreviouslyVisited(KMMove Move) const { return IsNotPreviouslyVisited(Move.GetNextLocation()); }
bool IsNotPreviouslyVisited(KMBoardLocation Destination) const;
public:
KMMoveFilters(void);
KMMoveFilters(unsigned int BoardDimension, KnightMovesMethodLimitations SlicingMethod);
void ResetFilters(unsigned int BoardDimension, KnightMovesMethodLimitations SlicingMethod) {m_SingleSideBoardDimension = BoardDimension; m_PathLimitations = SlicingMethod; }
virtual ~KMMoveFilters(void);
void PushVisited(KMBoardLocation Location);
void PopVisited();
KMRandomAccessMoveCollection GetPossibleMoves(const KMBoardLocation CurrentLocation) const;
};
#endif /* KMMOVEFILTERS_H_ */
仅限KMMoveFilters.cpp中的更改
KMRandomAccessMoveCollection KMMoveFilters::GetPossibleMoves(const KMBoardLocation CurrentLocation) const
{
KMRandomAccessMoveCollection SafeAllPossibleMoves = AllPossibleMoves;
KMRandomAccessMoveCollection PossibleMoves;
for (auto PossibleMove : SafeAllPossibleMoves) {
PossibleMove.SetBoardDimension(m_SingleSideBoardDimension);
PossibleMove.SetOriginCalculateDestination(CurrentLocation);
if ((PossibleMove.IsValid()) && (IsNotPreviouslyVisited(PossibleMove))) {
PossibleMoves.push_back(PossibleMove);
}
}
return PossibleMoves;
}
结果输出
选择要运行的测试用例的编号
测试用例#开始名称目标名称板尺寸切片方法
1 A3 H4 8无法返回上一行或列
2 A1 H8 8无法返回上一行或列
3 A8 H1 8无法返回上一行或列
4 B3 H4 8无法返回上一行或列
5 B3 H8 8无法返回上一行或列
6 C1 H4 8无法返回上一行或列
7 A3 H8 8无法返回上一行或列
8 A3 B5 8无法返回上一行或列
9 H4 A3 8无法返回上一行或列
10 D4 A8 8无法返回上一行或列
11 D4 E6 8无法返回上一行或列
12 A3 B5 12无法返回上一行或列
13 A3 B5 8无法返回上一个位置
14 A3 B5 26无法返回上一行或列
15以上所有以上除13和14外
16以上所有(去吃午餐)
完成计算0 经过时间:0.209012秒
所有路径搜索的起始点是A3
所有路径搜索的目标点是H4
电路板每个边缘的方格数为8
用于进一步限制搜索的切片方法是不会重复访问任何行或列
共有5条生成路径
有323个尝试路径
平均路径长度为4.8
中值路径长度为4
最长的路径是6次移动
最短的路径是4次移动
完成计算0 已用时间:0.0930054秒
所有路径搜索的起始点是A1
所有路径搜索的目标点是H8
电路板每个边缘的方格数为8
用于进一步限制搜索的切片方法是不会重复访问任何行或列
共有22条生成路径
有160个尝试路径
平均路径长度为6.36364
中值路径长度为6
最长的路径是8次移动
最短路径是6次移动
完成计算0 已用时间:0.0950054秒
所有路径搜索的起点是A8
所有路径搜索的目标点都是H1
电路板每个边缘的方格数为8
用于进一步限制搜索的切片方法是不会重复访问任何行或列
共有22条生成路径
有160个尝试路径
平均路径长度为6.36364
中值路径长度为6
最长的路径是8次移动
最短路径是6次移动
完成计算0 经过时间:0.248014秒
所有路径搜索的起点都是B3
所有路径搜索的目标点是H4
电路板每个边缘的方格数为8
用于进一步限制搜索的切片方法是不会重复访问任何行或列
共有8条生成路径
有446个尝试路径
平均路径长度为5
中值路径长度为5
最长的路径是7次移动
最短的路径是3次移动
完成计算0 已用时间:0.251014秒
所有路径搜索的起点都是B3
所有路径搜索的目标点是H8
电路板每个边缘的方格数为8
用于进一步限制搜索的切片方法是不会重复访问任何行或列
共有39条生成路径
有447个尝试路径
平均路径长度为6.23077
中值路径长度为7
最长的路径是7次移动
最短路径是5次移动
完成计算0 已用时间:0.17801秒
所有路径搜索的起始点是C1
所有路径搜索的目标点是H4
电路板每个边缘的方格数为8
用于进一步限制搜索的切片方法是不会重复访问任何行或列
共有7条生成路径
有324个尝试路径
平均路径长度为4.85714
中值路径长度为4
最长的路径是6次移动
最短的路径是4次移动
完成计算0 经过时间:0.18201秒
所有路径搜索的起始点是A3
所有路径搜索的目标点是H8
电路板每个边缘的方格数为8
用于进一步限制搜索的切片方法是不会重复访问任何行或列
共有36条结果路径
有324个尝试路径
平均路径长度为6
中值路径长度为6
最长的路径是8次移动
最短的路径是4次移动
完成计算0 已用时间:0.131008秒
所有路径搜索的起始点是A3
所有路径搜索的目标点是B5
电路板每个边缘的方格数为8
用于进一步限制搜索的切片方法是不会重复访问任何行或列
共有6条生成路径
有243个尝试路径
平均路径长度为3
中值路径长度为3
最长的路径是5次移动
最短路径是1次移动
完成计算0 已用时间:0.17301秒
所有路径搜索的起点都是H4
所有路径搜索的目标点是A3
电路板每个边缘的方格数为8
用于进一步限制搜索的切片方法是不会重复访问任何行或列
有12条结果路径
有318个尝试路径
平均路径长度为5.66667
中值路径长度为6
最长的路径是8次移动
最短的路径是4次移动
完成计算0 经过时间:0.332019秒
所有路径搜索的起点是D4
所有路径搜索的目标点是A8
电路板每个边缘的方格数为8
用于进一步限制搜索的切片方法是不会重复访问任何行或列
有24条结果路径
有602个尝试路径
平均路径长度为5.25
中值路径长度为5
最长的路径是7次移动
最短的路径是3次移动
完成计算0 经过时间:0.266015秒
所有路径搜索的起点是D4
所有路径搜索的目标点是E6
电路板每个边缘的方格数为8
用于进一步限制搜索的切片方法是不会重复访问任何行或列
共有21条结果路径
有487条尝试路径
平均路径长度为4.14286
中值路径长度为5
最长的路径是7次移动
最短路径是1次移动
完成计算0 已用时间:1.86411秒
所有路径搜索的起始点是A3
所有路径搜索的目标点是B5
电路板每个边缘的方格数为12
用于进一步限制搜索的切片方法是不会重复访问任何行或列
共有6条生成路径
有3440个尝试路径
平均路径长度为3
中值路径长度为3
最长的路径是5次移动
最短路径是1次移动
总体结果
平均执行时间为0.335186秒
中位执行时间为0.209012秒
最长执行时间为1.86411秒
最短执行时间为0.0930054秒
优化版本的总体结果。
总体结果
平均执行时间为0.00266682秒
中位执行时间为0.0020001秒
最长执行时间为0.0140008秒
最短的执行时间是0.001秒
CentOS版本整体结果
平均执行时间为0.00195405秒
中位执行时间为0.00103346秒
最长执行时间为0.00130368秒
最短执行时间为0.000716237秒