<html>

<head><script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<!-- MyFirstUnitAd -->
<ins class="adsbygoogle"
     style="display:inline-block;width:970px;height:250px"
     data-ad-client="ca-pub-5778386704669218"
     data-ad-slot="1503492166"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>

<meta http-equiv="Content-Language" content="zh-cn">
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<title>Population</title>
</head>

<body>



<p align="left"><font size="6" color="#FF0000"><b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DFSArray---New 
Knight</b></font></p>

<div align="left">
  <pre><b><font color="#ff0000" size="5">A.<span lang="en-ca"> </span>Third Edition</font></b></pre>
</div>
<div align="left">
  <pre><b>This is <span lang="en-ca">my </span>third<span lang="en-ca"> edition of </span>my DFS class implemented with an array<span lang="en-ca"> (The second edition never appear on web as it</span></b></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><b>is only a minor different from first edition. </b></span><b> Or you can call it second version of Knights-tour problem which I</b></pre>
</div>
<div align="left">
  <pre><b>wrote long before with a series of functions.</b></pre>
</div>
<div align="left">
  <pre><b><font color="#ff0000" size="5"><span lang="en-ca">B</span>.<span lang="en-ca"><a name="problem"></a>The problem</span></font></b></pre>
</div>
<div align="left">
  <b><font size="2">A knight on a chess board starting from a certain position 
  wants to jump to all position of board </font></b></div>
<div align="left">
  　</div>
<div align="left">
  <b><font size="2">once and only once<span lang="en-ca"> with 64 jumps for a 
  standard chess board</span>. How?&nbsp; This problem was proposed by 
  Euler.</font></b></div>
<div align="left">
  　</div>
<div align="left">
  <b><font color="#ff0000" size="5"><span lang="en-ca">C</span>.<span lang="en-ca">The
  </span></font></b><span lang="en-ca"><font size="5" color="#FF0000"><b>idea of 
  program</b></font></span></div>
<div align="left">
  <pre><b>There is a big change in this edition that I changed the dynamic allocating nodes to be a kind of pre-created </b></pre>
</div>
<div align="left">
  <pre><b>nodes. It is meaningless to &quot;new&quot; and &quot;delete&quot; those nodes<span lang="en-ca"> since the nodes remains there, only that the data</span></b></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><b>inside nodes changes</b></span><b>.<span lang="en-ca"> So, why don't we just change the data instead of creating and deleting nodes?</span></b></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><b>However, most part of code of previous version remains unchanged. I only initialize all pointers in the pointer</b></span></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><b>array to point to a real derived class objects. And won't delete them until end of program. When son node is created</b></span></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><b>only data in the node was initialized, but not the object was created as it is created already first time.</b></span></pre>
</div>
<div align="left">
  <pre><b><font size="5" color="#FF0000">D.<span lang="en-ca"><a name="Method"></a>The </span>major functions</font></b></pre>
</div>
<div align="left">
  <pre><b>1.<span lang="en-ca"> void DFS::addSon(int sonData)</span></b></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><b>This function now only points to the son node without &quot;new&quot; a son node object.</b></span></pre>
</div>
<div align="left">
  <pre><b>2. virtual void onBeginSearch();</b></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><b>This virtual function gives user opportunity to initialize data just before searching starts.</b></span></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><b>3. virtual void onAfterAdded();</b></span></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><b>This function gives user opportunity to synchronize data between parent and son just after son node is created.</b></span></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><b>4. virtual DFS* createSon() = 0;</b></span></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><b>Now this function is only called in base class to create all nodes in the first time to guarentee it is creating</b></span></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><b>son node.</b></span></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><b>5. 
</b></span></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><font size="5" color="#FF0000"><b>E</b></font></span><b><font color="#ff0000" size="5">.</font></b><span lang="en-ca"><font size="5" color="#FF0000"><b>Further improvement</b></font></span></pre>
</div>
<div align="left">
  <pre><b>1.<span lang="en-ca"> </span></b><span lang="en-ca"><b>There is trade off for OOP as it slows down program execution by too many object operations. </b></span></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><b>2. Should add weight concept in next eddiition just as before.</b></span></pre>
</div>
<pre>　</pre>
<pre><b><font color="#FF0000" size="3">//file DFSArray.h
</font></b>
#ifndef DFSARRAY_H
#define DFSARRAY_H
#include &lt;iostream&gt;

using namespace std;

const int MaxSonCount=8;

const int MaxLevel = 120;

const int MaxOptions = 16;

const int MaxNodeCount = 300;

class DFS
{
private:
	void initialize(DFS* now);
	static bool initialized;
	static DFS* nodeList[MaxNodeCount];
	static bool findAll;
	static int optionArray[MaxOptions];
	static int optionCount;
	static char** nameString;
	static int solutionCount;
	static int maxLevel;
	void addSon(int sonData);
	bool touchDown();
	void setMaxLevel(int max) { maxLevel = max;}
	DFS* upDate();
	static int domino;
	bool hasBrother();
	DFS* nextBrother();
	bool generate();
	DFS* findNext();
	DFS* getNode(int theIndex){return nodeList[theIndex];}
	void putNode(int theIndex) { nodeList[theIndex] = this;}
	bool hasParent(){return parent!=-1;}
protected:
	int parent;
	int sonCount;
	int sonIndex;
	int son;
	int depth;
	int index;//index in nodeList
	int data;
	static int trackRecord[MaxLevel];
	void backTrack();
	DFS* getParent(){return getNode(parent);}
	virtual void onAfterAdded();
	virtual void onGenerate();
	virtual void onBeginSearch();
	virtual DFS* createSon() = 0;
	virtual bool validateOption(int sonData) =0;	//made it pure virtual
	virtual void onLeave();
	virtual bool evaluate() = 0;
	virtual void collectResult();
public:
	int getSolutionCount(){ return solutionCount;}
	void setOptions(int* array, int size);
	void setNameStr(char** str){nameString = str;}
	bool beginCount(int max, bool findall=false);
	virtual ~DFS();//virtual destructor
};

#endif</pre>
<pre>　</pre>
<pre><b><font color="#FF0000" size="3">//file DFSArray.cpp
</font></b>
#include &lt;iostream&gt;
#include &quot;DFSArray.h&quot;

using namespace std;

int DFS::domino = 0;
bool DFS::findAll = false;
bool DFS::initialized = false;
int DFS::maxLevel = 0;
int DFS::optionArray[MaxOptions] = {0};
char** DFS::nameString=NULL;
int DFS::solutionCount = 0;
int DFS::optionCount = 0;
DFS* DFS::nodeList[MaxNodeCount] = {NULL};
int DFS::trackRecord[MaxLevel]= {0};


bool DFS::touchDown()
{
	return depth==maxLevel;
}

void DFS::onBeginSearch()
{
	//programmer may need do some initializing job here!
}

void DFS::onAfterAdded()
{
	//programmer may need do something for his own purpose
}

void DFS::onLeave()
{
	DFS* ptr =this;
	if (ptr-&gt;hasParent())
	{
		DFS* father = ptr-&gt;getParent();
		/*
		for (int i= father-&gt;son; i&lt;father-&gt;sonCount; i++)
		{
			delete nodeList[i];
			nodeList[i] = NULL;
		}
		*/
		domino -= father-&gt;sonCount;
		father-&gt;sonCount = 0;
		father-&gt;son = -1;	
	}	
}

void DFS::backTrack()
{
	DFS* ptr = this;

	while (ptr-&gt;hasParent())
	{
		trackRecord[ptr-&gt;depth-1] = ptr-&gt;data;
		ptr = ptr-&gt;getParent();
	}
}


//a stack
void DFS::collectResult()
{
	backTrack();
	cout&lt;&lt;&quot;The route is:\n&quot;;
	for (int i=0; i&lt;depth; i++)
	{
		cout&lt;&lt;nameString[trackRecord[i]]&lt;&lt;&quot;, &quot;;
	}
	cout&lt;&lt;&quot;\nIt is number:&quot;&lt;&lt;solutionCount++;
	cout&lt;&lt;endl;
}

void DFS::setOptions(int *array, int size)
{
	optionCount = size;
	for (int i=0; i&lt;size; i++)
	{
		optionArray[i] = *(array+i);
	}
}

DFS::~DFS()
{
	if (initialized)
	{
		for (int i=1; i&lt;MaxNodeCount; i++)//the i=0 is root which is not dynamic allocated!
		{
			delete nodeList[i];
		}
		domino =0;
		initialized=false;
	}
}


void DFS::onGenerate()
{
	//programmer may need to initialize at this stage
}


bool DFS::beginCount(int max, bool findall)
{
	DFS* ptr = this;
	setMaxLevel(max);
	findAll = findall; //setup if want all result
	initialize(this);
	onBeginSearch();//this is done from root!

	while (ptr!=NULL)
	{
		//programmer may need to initialize at this stage
		ptr-&gt;onGenerate();
		if (ptr-&gt;generate())
		{
			ptr = ptr-&gt;upDate();//move to first son			
			if (ptr-&gt;evaluate())
			{
				ptr-&gt;collectResult();
				if (!findAll)
				{
					break;
				}
				else
				{
					ptr = ptr-&gt;findNext();
									
				}
			}
			else
			{
				if (ptr-&gt;touchDown())//for a new son
				{
					ptr=ptr-&gt;findNext();
										
				}
			}
		}
		else
		{
			ptr = ptr-&gt;findNext();//for a new son
			
		}
	}
	if (solutionCount==0)
	{
		cout&lt;&lt;&quot;no solution!&quot;;
		return false;
	}
	else
	{
		cout&lt;&lt;&quot;Total solution is &quot;&lt;&lt;solutionCount&lt;&lt;endl;
		return true;
	}
		
}
	
DFS* DFS::findNext()
{
	DFS* ptr = this;
	DFS* dummy;
	while (ptr!=NULL)
	{
		if (ptr-&gt;hasBrother())
		{
			ptr = getNode(ptr-&gt;index+1);//next brother
			
			return ptr;			
		}
		else
		{
			if (ptr-&gt;hasParent())
			{
				dummy = ptr;
				ptr = ptr-&gt;getParent(); //if 
				dummy-&gt;onLeave(); //only clear when go up one level
			}
			else
			{
				break;
			}
		}
	}
	return NULL;
}

bool DFS::generate()
{
	bool result = false;
	if (touchDown())
	{
		return false;
	}
	//this is preorder and I don't bother to 
	//give choices for midorder or postorder
	for (int i=0; i&lt; optionCount; i++)
	{
		if (validateOption(optionArray[i]))
		{
			addSon(optionArray[i]);
			result = true;		
		}
	}
	return result;
}


DFS* DFS::upDate()
{
	//return first son	
	return getNode(son);
}

/* a pure virtual
//must be override by user when inherited
DFS* DFS::createSon()
{
	DFS* ptr = new DFS;
	return ptr;
}
*/


void DFS::addSon(int sonData)
{	
	if (sonCount+1&lt;MaxSonCount)
	{
		if (domino==MaxNodeCount)
		{
			cout&lt;&lt;&quot;Exceeds limit of node list&quot;&lt;&lt;endl;
			return;
		}
		//DFS* ptr = createSon();
		DFS* ptr = nodeList[domino];
		ptr-&gt;index = domino;//
		//ptr-&gt;putNode(domino);		

		if (sonCount==0)//if it is the first son
		{
			son = domino;//first son 
		}
		domino++;
		ptr-&gt;data = sonData;
		ptr-&gt;sonCount = 0;
		ptr-&gt;son = -1;//temporarily
		ptr-&gt;parent = index;
		ptr-&gt;depth = depth+1;
		ptr-&gt;sonIndex = sonCount;
		sonCount++;
		ptr-&gt;onAfterAdded();
	}
	else
	{
		cout&lt;&lt;&quot;Exceed max of sons!&quot;;
	}
}

void DFS::initialize(DFS* now)
{
	now-&gt;index =0;	
	now-&gt;depth = 0;
	now-&gt;sonCount = 0;
	now-&gt;sonIndex = -1;
	now-&gt;parent = -1;
	now-&gt;data = 0;
	now-&gt;son = -1;
	now-&gt;putNode(0); //put in list

	if (!initialized)
	{
		for (int i=1; i&lt;MaxNodeCount; i++)
		{
			nodeList[i] = createSon();
		}
		initialized = true;
	}
	domino++;
}

bool DFS::hasBrother()
{
	if (hasParent())
	{
		if (getParent()-&gt;sonCount &gt; sonIndex+1)//has little brother
		{
			return true;
		}
	}
	return false;
}</pre>
<pre>
</pre>
<pre><b><font color="#FF0000" size="3">//file Knights.cpp
</font></b>
#include &lt;iostream&gt;
#include &quot;DFSArray.h&quot;
using namespace std;

const int BoardSize = 6;


enum MoveType
{RightUp, UpRight, UpLeft, LeftUp, LeftDown, DownLeft, DownRight, RightDown};

int moveChoice[8] = 
	{RightUp, UpRight, UpLeft, LeftUp, LeftDown, DownLeft, DownRight, RightDown};

char* moveStr[8] = 
{&quot;RightUp&quot;, &quot;UpRight&quot;, &quot;UpLeft&quot;, &quot;LeftUp&quot;, &quot;LeftDown&quot;, &quot;DownLeft&quot;, &quot;DownRight&quot;, &quot;RightDown&quot;};


struct Pos
{
	int x;
	int y;
};

Pos startPos = {0,0};


class Knights: public DFS
{
	bool board[BoardSize][BoardSize];
	Pos pos;
	Pos testMove(MoveType theMove, Pos thePos);
	void move(MoveType theMove);
protected:
	void onAfterAdded();
	void onBeginSearch();
	DFS* createSon();
	bool validateOption(int sonData);
	bool evaluate();
	void collectResult();
public:
};

int main()
{
	Knights K;
	K.setOptions(moveChoice, 8);
	K.setNameStr(moveStr);
	for (int r=0; r&lt;BoardSize/2; r++)
	{
		for (int c =0; c&lt;r+1; c++)
		{
			startPos.x = r;
			startPos.y = c;
			cout&lt;&lt;&quot;startPos(&quot;&lt;&lt;r&lt;&lt;','&lt;&lt;c&lt;&lt;&quot;) is:&quot;;
			if (K.beginCount(BoardSize*BoardSize, true))
			{
				return 0;
			}
			cout&lt;&lt;endl&lt;&lt;endl;

		}
	}
	return 0;
}


void Knights::onAfterAdded()
{
	DFS* ptr = getParent();
	for (int r=0; r&lt;BoardSize; r++)
	{
		for (int c=0; c&lt;BoardSize; c++)
		{
			board[r][c] = ((Knights*)(ptr))-&gt;board[r][c];
		}
	}
	pos = ((Knights*)(ptr))-&gt;pos;
	if (depth!=0)
	{
		move((MoveType)(data));
	}
}

void Knights::collectResult()
{
	int temp[BoardSize][BoardSize]={0};
	Pos curPos = startPos;

	DFS::collectResult();//do what should be done first
	for (int i=0; i&lt;BoardSize*BoardSize; i++)
	{
		temp[curPos.x][curPos.y] = i+1;
		curPos = testMove((MoveType)(trackRecord[i]), curPos);
	}
	cout&lt;&lt;endl;
	for (int r=0; r&lt;BoardSize; r++)
	{
		for (int c=0; c&lt;BoardSize; c++)
		{
			cout&lt;&lt;temp[r][c]&lt;&lt;'\t';
		}
		cout&lt;&lt;endl;
	}
}

bool Knights::evaluate()
{
	return depth==BoardSize*BoardSize;
}

bool Knights::validateOption(int sonData)
{
	Pos temp = testMove((MoveType)(sonData), pos);
	if (temp.x&lt;0||temp.x&gt;BoardSize-1||temp.y&lt;0||temp.y&gt;BoardSize-1)
	{
		return false;
	}
	if (board[temp.x][temp.y])
	{
		return false;
	}
	return true;
}

void Knights::onBeginSearch()
{
	for (int r=0; r&lt;BoardSize; r++)
	{
		for (int c=0; c&lt;BoardSize; c++)
		{
			board[r][c] = false;
		}
	}
	board[startPos.x][startPos.y] = true;
	pos = startPos;

}

//copy data from parent
DFS* Knights::createSon()
{
	DFS* ptr = new Knights;
	if (ptr==NULL)
	{
		cout&lt;&lt;&quot;unable to create new node!\n&quot;;
	}

	return ptr;
}




Pos Knights::testMove(MoveType theMove, Pos thePos)
{
	Pos temp = thePos;
	switch (theMove)
	{
	case RightUp:
		temp.x += 2;
		temp.y -= 1;
		break;
	case UpRight:
		temp.x += 1;
		temp.y -= 2;
		break;
	case UpLeft:
		temp.x -= 1;
		temp.y -= 2;
		break;
	case LeftUp:
		temp.x -= 2;
		temp.y -= 1;
		break;
	case LeftDown:
		temp.x -= 2;
		temp.y += 1;
		break;
	case DownLeft:
		temp.x -= 1;
		temp.y += 2;
		break;
	case DownRight:
		temp.x += 1;
		temp.y += 2;
		break;
	case RightDown:
		temp.x += 2;
		temp.y += 1;
		break;
	}
	return temp;
}


void Knights::move(MoveType theMove)
{
	pos = testMove(theMove, pos);
	board[pos.x][pos.y] = true;
}



</pre>
<pre>
</pre>
<pre></pre>
<pre></pre>
<pre><b><font color="#FF0000" size="3"><span lang="en-ca"><a name="result"></a>Running result of program:</span></font></b></pre>
<pre></pre>
<pre>　</pre>
<pre>	</pre>
<pre></pre>
<pre>			
</pre>

<pre></pre>

<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;                                   
&nbsp;&nbsp;&nbsp; <a href="WhoAmI.htm">                  







                       <img src="picture/back.gif" style="border: medium none" alt="back.gif (341 bytes)" width="32" height="35"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
<a href="index.htm"><img src="picture/up.gif" style="border: medium none" alt="up.gif (335 bytes)" width="35" height="32"></a>       &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;                         
<img src="picture/next.gif" style="border: medium none" alt="next.gif (337 bytes)" width="32" height="35">          


</p>

</body>

</html>