罗马尼亚度假问题和N皇后问题
来源:互联网 发布:淘宝直通车图片优化 编辑:程序博客网 时间:2024/04/30 07:28
罗马尼亚度假问题主体代码
#ifndef NODEEDGE#define NODEEDGEextern class cMap;class cMapEdge;class cMapNode;//-----------------------------------------------------------------------//图的边class cMapEdge{public: //边到达的结点的在结点数组中的下标 int m_edgeDesIndex; //边的权值 double m_edgeWeight; //指向下一条边 cMapEdge * m_pEdge;public: cMapEdge(int des = -1, double weight = -1, cMapEdge * pEdge = NULL); //拷贝构造函数 cMapEdge(cMapEdge & edge); //重载赋值操作符 cMapEdge & operator =(const cMapEdge& edge); ~cMapEdge(){}};//---------------------------------------------------------//图的结点class cMapNode{ friend class Map;public: string m_nodeName; double m_nodeValue; //结点在链表中的下标 int m_nodeIndex; cMapNode * m_pNextNode; cMapEdge * m_pEdge;public: cMapNode(string name = "", double value = -1, int index = -1, cMapEdge * pEdge = NULL, cMapNode * pNext = NULL); ~cMapNode(){} void AddEdge(int endIndex = -1, double weight = -1); //复制构造函数,为了更快的访问结点信息,使用浅复制就行 cMapNode(cMapNode & node); //=复制操作重载 cMapNode & operator =(const cMapNode & node);};#endif
#include "afxfunc.h"#include "NodeEdge.h"//----------------------------------------------------------------------------------------------------------------------cMapEdge::cMapEdge(int des, double weight, cMapEdge *pEdge){ m_edgeDesIndex = des; m_edgeWeight = weight; m_pEdge = pEdge;}cMapEdge::cMapEdge(cMapEdge & edge){ m_edgeDesIndex = edge.m_edgeDesIndex; m_edgeWeight = edge.m_edgeWeight; m_pEdge = edge.m_pEdge;}cMapEdge & cMapEdge::operator =(const cMapEdge& edge){ m_edgeDesIndex = edge.m_edgeDesIndex; m_edgeWeight = edge.m_edgeWeight; m_pEdge = edge.m_pEdge; return *this;}//-------------------------------------------------------------------------------------------------------------------------cMapNode::cMapNode(string name, double value, int index, cMapEdge *pEdge, cMapNode *pNext){ m_nodeName = name; m_nodeValue = value; m_nodeIndex = index; m_pEdge = pEdge; m_pNextNode = pNext;}void cMapNode::AddEdge(int endIndex, double weight){ m_pEdge = new cMapEdge(endIndex, weight, NULL);}//复制构造函数,为了更快的访问结点信息,使用浅复制就行cMapNode::cMapNode(cMapNode & node){ m_nodeIndex = node.m_nodeIndex; m_nodeName = node.m_nodeName; m_nodeValue = node.m_nodeValue; m_pNextNode = node.m_pNextNode; m_pEdge = node.m_pEdge;}//=复制操作重载cMapNode & cMapNode::operator =(const cMapNode & node){ m_nodeIndex = node.m_nodeIndex; m_nodeName = node.m_nodeName; m_nodeValue = node.m_nodeValue; m_pNextNode = node.m_pNextNode; m_pEdge = node.m_pEdge; return *this;}
#ifndef MAP#define MAP#include "NodeEdge.h"//邻接矩阵保存图//-----------------------------------------------------//封装结点name和下标减少遍历次数struct sNameIndex{ string m_name; int m_index; sNameIndex(string name = "", int index = -1) :m_name(name), m_index(index){}};//封装结点name,下标和深度减少遍历次数struct sNameIndexDepth{ string m_name; int m_index; int m_depth; sNameIndexDepth(string name = "", int index = -1,int depth=-1) :m_name(name), m_index(index){}};//-----------------------------------------------------class cMap{private: //结点集的首指针 cMapNode * m_pHeadNode; //图的结点数量 int m_size; //为方便访问结点而定义的 cMapNode *m_pCurr;public: int COUNT ; //默认构造函数 cMap(); //析构函数,显式delete结点集和边集 ~cMap(); //从文件中载入结点 void LoadNodeFromFile(string path = "G://C++//SearchPro1//node.txt"); //从文件载入边集 void LoadEdgeFromFile(string path = "G://C++//SearchPro1//edge.txt"); //添加边 void AddEdge(int endIndex=-1,double weight=-1); //添加结点 void AddNode(string nodeName="",double nodeValue=-1,int index=-1); //获取结点 cMapNode* GetNodeByName(string nodeName = ""); cMapNode* GetNodeByIndex(int index = -1); //获取结点在链表中位置和name sNameIndex cMap::GetNodeNamePos(const string nodeName="",const int position=-1); //代价一致的广度优先搜索,返回路径数组 string BFSearch(string startName = "", string endName = ""); //预设搜索深度的深度优先搜索,返回路径数组 string DLSearch(string startName = "", string endName = "", int depth = 20); //考虑启发值的贪婪搜索,深度优先,返回路径数组 string GSearch(string startName = "", string endName = ""); //A*搜索根据启发值与边长,深度优先,与Dijkstra一样把全部路径找出来,返回路径数组(最短) string ASearch(string startName = "", string endName = ""); //根据sNameIndex[]里的信息构建path string GetPath(sNameIndex * path, int finalIndex = -1); string GetPathD(sNameIndexDepth * path, int finalIndex = -1);};#endif
#include "afxfunc.h"#include "Map.h"#include "LinQueue.h"#include "LinStack.h"//--------------------------------------------------------------------------------------------------------------------------//默认构造函数cMap::cMap(){ COUNT = (0); m_pCurr = NULL; m_pHeadNode = NULL; m_size = 0;}//析构函数,显式delete结点集和边集cMap::~cMap(){}//从文件中载入结点void cMap::LoadNodeFromFile(string path){ string name = ""; double value = -1; string line; ifstream ifs; ifs.open(path); if (ifs.is_open()) { cMapNode * p; cMapNode * q = NULL; while (!ifs.eof()) { getline(ifs, line); int pos = line.find('\t'); name = line.substr(0, pos); istringstream iss(line.substr(pos + 1, line.length())); iss >> value; if (q == NULL) { m_pHeadNode = new cMapNode(name, value, m_size, NULL, NULL); m_pCurr = m_pHeadNode; q = m_pHeadNode; } else { p = new cMapNode(name, value, m_size, NULL, NULL); q->m_pNextNode = p; q = q->m_pNextNode; } m_size++; } } ifs.close();}//从文件载入边集void cMap::LoadEdgeFromFile(string path){ cMapNode * pCurr = m_pHeadNode; cMapEdge * pTemp; cMapEdge *pBefTemp = NULL; ifstream ifs; string line; ifs.open(path); if (ifs.is_open()) { int eIndex = 0; while (!ifs.eof()) { getline(ifs, line); istringstream iss(line); double weight; while (iss >> weight) { if (weight > MIN_WEIGHT&&weight < MAX_WEIGHT) { pTemp = new cMapEdge(eIndex, weight, NULL); if (pBefTemp == NULL) { pCurr->m_pEdge = pTemp; pBefTemp = pCurr->m_pEdge; } else { pBefTemp->m_pEdge = pTemp; pBefTemp = pBefTemp->m_pEdge; } } eIndex++; } pBefTemp = NULL; //边对应结点下标归0 eIndex = 0; //下一行边对应下一行的结点 pCurr = pCurr->m_pNextNode; } } ifs.close();}//添加边void cMap::AddEdge(int endIndex, double weight){}//添加结点void cMap::AddNode(string nodeName, double nodeValue, int nodeIndex){}//获取结点cMapNode* cMap::GetNodeByName(string nodeName){ m_pCurr = m_pHeadNode; while (m_pCurr != NULL) { if (m_pCurr->m_nodeName == nodeName)return m_pCurr; m_pCurr = m_pCurr->m_pNextNode; } cout << "error nodeName" << endl; exit(0);}cMapNode* cMap::GetNodeByIndex(int index){ if (index > -1 && index < m_size) { m_pCurr = m_pHeadNode; while (index) { m_pCurr = m_pCurr->m_pNextNode; index--; } return m_pCurr; } cout << "error nodeName" << endl; exit(0);}//获取结点在链表中位置sNameIndex cMap::GetNodeNamePos(const string nodeName, const int position){ int pos = position; if (pos > -1 && pos < m_size) { m_pCurr = m_pHeadNode; while (pos) { m_pCurr = m_pCurr->m_pNextNode; pos--; } return sNameIndex(m_pCurr->m_nodeName, position); } if (nodeName != "") { m_pCurr = m_pHeadNode; while (m_pCurr != NULL) { pos++; if (m_pCurr->m_nodeName == nodeName)return sNameIndex(nodeName, pos); m_pCurr = m_pCurr->m_pNextNode; } } return sNameIndex("", -1);}//代价一致的广度优先搜索,返回路径string cMap::BFSearch(string startName, string endName){ if (startName == endName)return "这是同一个结点"; sNameIndex *path = new sNameIndex[m_size+1]; cMapNode * curr = m_pHeadNode; for (int a = 0; a < m_size; ++a) { path[a].m_name = curr->m_nodeName; curr = curr->m_pNextNode; } //保存当前开始结点在path的下标 int childIndex = GetNodeNamePos(startName, -1).m_index; int parentIndex = -2; //标记当前开始结点的前继结点下标为-2 path[childIndex].m_index = parentIndex; //将开始结点存入队列 cLinQueue<cMapNode> nodeQueue; nodeQueue.Append(*GetNodeByName(startName)); while (nodeQueue.NotEmpty()) { //队头结点出队列 cMapNode curr = nodeQueue.Delete(); //出队列的结点将作为父结点 parentIndex = curr.m_nodeIndex; //获取curr连通的所有边 cMapEdge *pNextEdge = curr.m_pEdge; while (pNextEdge != NULL) { //根据连通的边找到边连接的结点及其信息 cMapNode* pNextNode = GetNodeByIndex(pNextEdge->m_edgeDesIndex); //获取子结点在path中的下标,并标记它的父结点 childIndex = pNextNode->m_nodeIndex; //如果连通的结点已被标记就不再重复 if (path[childIndex].m_index != -1) { pNextEdge = pNextEdge->m_pEdge; continue; } path[childIndex].m_index = parentIndex; //判断将入队列的结点是不是待求结点 if (pNextNode->m_nodeName == endName)return GetPath(path, childIndex); //否则连通的结点入队列 nodeQueue.Append(*pNextNode); pNextEdge = pNextEdge->m_pEdge; } } //队列空了,路径还没找到 delete[] path; path = NULL; return "can not found a path";}//预设搜索深度的深度优先搜索,返回路径string cMap::DLSearch(string startName, string endName, int depth){ if (startName == endName)return "这是同一个结点"; sNameIndexDepth *path = new sNameIndexDepth[m_size+1]; cMapNode * curr = m_pHeadNode; for (int a = 0; a < m_size; ++a) { path[a].m_name = curr->m_nodeName; curr = curr->m_pNextNode; } //保存当前开始结点在path的下标 int childIndex = GetNodeNamePos(startName, -1).m_index; int parentIndex = -2; //标记当前开始结点的下标为-2 path[childIndex].m_index = parentIndex; path[childIndex].m_depth = 0; //将开始结点存入栈 cLinStack<cMapNode> nodeStack; nodeStack.Push(*GetNodeByName(startName)); while (nodeStack.NotEmpty()) { //队头结点出栈 cMapNode curr = nodeStack.Pop(); if (curr.m_nodeName == endName)return GetPathD(path, curr.m_nodeIndex); //出队列的结点将作为父结点 parentIndex = curr.m_nodeIndex; if (path[curr.m_nodeIndex].m_depth < depth) { //获取curr连通的所有边 cMapEdge *pNextEdge = curr.m_pEdge; while (pNextEdge != NULL) { //根据连通的边找到边连接的结点及其信息 cMapNode* pNextNode = GetNodeByIndex(pNextEdge->m_edgeDesIndex); //获取子结点在path中的下标,并标记它的父结点 childIndex = pNextNode->m_nodeIndex; //如果连通的节点已被标记就不再重复 if (path[childIndex].m_index != -1&&path[childIndex].m_depth < path[parentIndex].m_depth + 1) { pNextEdge = pNextEdge->m_pEdge; continue; } path[childIndex].m_index = parentIndex; path[childIndex].m_depth = path[parentIndex].m_depth + 1; //判断将入栈的结点是不是待求结点 if (pNextNode->m_nodeName == endName)return GetPathD(path, childIndex); //否则连通的结点入栈 nodeStack.Push(*pNextNode); pNextEdge = pNextEdge->m_pEdge; } } } //栈空了,路径还没找到 delete[] path; path = NULL; return "can not found a path";}//考虑启发值的贪婪搜索,启发值最小优先,深度优先,返回路径string cMap::GSearch(string startName, string endName){ if (startName == endName)return "这是同一个结点"; sNameIndexDepth *path = new sNameIndexDepth[m_size+1]; cMapNode * curr = m_pHeadNode; for (int a = 0; a < m_size; ++a) { path[a].m_name = curr->m_nodeName; path[a].m_depth = curr->m_nodeValue; curr = curr->m_pNextNode; } //保存当前开始结点在path的下标 int childIndex = GetNodeNamePos(startName, -1).m_index; int parentIndex = -2; //标记当前开始结点的下标为-2 path[childIndex].m_index = parentIndex; //从第一个结点开始扩展 curr = GetNodeByName(startName); while (curr->m_nodeName != endName) { //扩展的结点将作为父结点 parentIndex = curr->m_nodeIndex; //获取curr连通的所有边 cMapEdge *pNextEdge = curr->m_pEdge; //保存启发值 int minValue = MAX_VALUE; while (pNextEdge != NULL) { //根据连通的边找到边连接的结点及其信息 cMapNode* pNextNode = GetNodeByIndex(pNextEdge->m_edgeDesIndex); //判断同层之间启发值大小,并标记最小启发值对应的结点 if (minValue > pNextNode->m_nodeValue&&path[pNextNode->m_nodeIndex].m_index == -1) { curr = pNextNode; minValue = curr->m_nodeValue; } //为了避免搜索陷入死路,当扩展结点中出现终点时强制使算法结束 if (pNextNode->m_nodeName == endName) { curr = pNextNode; childIndex = curr->m_nodeIndex; path[childIndex].m_index = parentIndex; return GetPathD(path, childIndex); } pNextEdge = pNextEdge->m_pEdge; } //为了避免搜索陷入死循环,最后的一个结点将无法被扩展,所以minValue还是MAX_VALUE if (minValue == MAX_VALUE)return GetPathD(path, childIndex); //循环结束,curr是未被标记过的启发值最小的结点 //获取curr结点在path中的下标,并标记它的父结点 childIndex = curr->m_nodeIndex; path[childIndex].m_index = parentIndex; } //全图搜索完了还没找到路径还没找到 delete[] path; path = NULL; return "can not found a path";}//A*搜索根据启发值与距离,深度优先,与Dijkstra一样把全部路径找出来,返回路径(最短)string cMap::ASearch(string startName, string endName){ if (startName == endName)return "这是同一个结点"; sNameIndexDepth *open = new sNameIndexDepth[m_size+1]; sNameIndexDepth *close = new sNameIndexDepth[m_size+1]; cMapNode * curr = m_pHeadNode; for (int a = 0; a < m_size; ++a) { open[a].m_name = curr->m_nodeName; //在open表中depth被当最短路径来用 open[a].m_depth = MAX_VALUE; close[a].m_name = curr->m_nodeName; close[a].m_index = 0; //在close表中depth被当启发值来用 close[a].m_depth = curr->m_nodeValue; curr = curr->m_pNextNode; } //保存当前开始结点在path的下标 int childIndex = GetNodeNamePos(startName, -1).m_index; int parentIndex = -2; //标记当前开始结点的下标为-2 open[childIndex].m_index = parentIndex; //此时在open表中depth被当作路径距离来使用A距A的距离为0 open[childIndex].m_depth = 0; //将开始点从close列表取出,即close表中标记A已被访问 close[childIndex].m_index = 1; //开始结点 curr = GetNodeByName(startName); while (curr->m_nodeName != endName) { //开始结点将作为父结点 parentIndex = curr->m_nodeIndex; //获取curr连通的所有边 cMapEdge *pNextEdge = curr->m_pEdge; while (pNextEdge != NULL) { //根据连通的边找到边连接的结点及其信息 cMapNode* pNextNode = GetNodeByIndex(pNextEdge->m_edgeDesIndex); //获取子结点在path中的下标,并标记它的父结点 childIndex = pNextNode->m_nodeIndex; //如果连通的节点已被标记就不再重复 if (close[childIndex].m_index) { pNextEdge = pNextEdge->m_pEdge; continue; } //否则找到连通结点的下标,符合更新要求时更新父亲路径长度 if ((open[parentIndex].m_depth + pNextEdge->m_edgeWeight) < open[childIndex].m_depth) { open[childIndex].m_depth = (open[parentIndex].m_depth + pNextEdge->m_edgeWeight); open[childIndex].m_index = parentIndex; } pNextEdge = pNextEdge->m_pEdge; } //找未被访问的结点中路径最短+启发值最小的点 int min = MAX_VALUE; int i = 0; int i2 = 0; while (i<m_size) { if (!close[i].m_index && ( open[i].m_depth + close[i].m_depth) < min) { min=open[i].m_depth + close[i].m_depth; i2 = i; } ++i; } if (min == MAX_VALUE) { return startName+" can not reach "+endName; } curr = GetNodeByIndex(i2); close[i2].m_index = 1; } if (curr->m_nodeName == endName)return GetPathD(open, curr->m_nodeIndex); //栈路径没找到 delete[] open; delete[] close; open = NULL; close = NULL; return "can not found a path";}string cMap::GetPath(sNameIndex * path, int finalIndex){ string thePath = ""; int childIndex = finalIndex; int parentIndex = path[finalIndex].m_index; while (parentIndex != -2) { thePath += path[childIndex].m_name + " <- "; childIndex = parentIndex; parentIndex = path[childIndex].m_index; } thePath += path[childIndex].m_name; //reverse(thePath.begin(),thePath.end()); return thePath;}string cMap::GetPathD(sNameIndexDepth * path, int finalIndex){ string thePath = ""; int childIndex = finalIndex; int parentIndex = path[finalIndex].m_index; while (parentIndex != -2) { thePath += path[childIndex].m_name + " <- "; childIndex = parentIndex; parentIndex = path[childIndex].m_index; } thePath += path[childIndex].m_name; //reverse(thePath.begin(),thePath.end()); return thePath;}
N皇后问题
#ifndef NQUEENS#define NQUEENS#define DONE -1#define MINVALUE 0#include <iostream>#include <math.h>#include <time.h>using namespace std;class cNQueens{ //N int m_n; //记录总结果数 long m_sum; //for recursion long m_upperlim;public: cNQueens(int n = 0, long sum = 0) :m_n(n), m_sum(sum){ m_upperlim = 1; m_upperlim = (m_upperlim << n) - 1; } ~cNQueens(){}; void ResetSum(){ m_sum = 0; } int ReturnSum(){ return m_sum; } //row根据列禁用的本行皇后摆放位置,ld根据左斜线位置禁用的本行皇后摆放位置 //rd根据右斜线禁用的本行皇后摆放位置 //递归成功标志:row的值和(upperlim<<n)-1的值相等 void RecursionProcess(); bool Recursion(long row = 0, long ld = 0, long rd = 0); //GA需要定义种群规模和初始双亲 int GAProcess(long groupNum, short * &dad, short * &mom); double GetFit(short* & map, int depth = 1)const; double GetDone(short* & map)const; //不指定双亲时随机构造初始种群 int InitPop(short * &Dad, short * &Mom, long groupNum = 0); //根据双亲产生种群并更新双亲 int GACrossVariation(short * &dad, short * &mom, long groupNum); //最小冲突CSP算法 int CSPProcess(short* & solution); int CSPSearch(short* & solution); bool Done(short* & row, short* &rd, short* & ld);};//----------------------------------------------------------void cNQueens::RecursionProcess(){ ResetSum(); Recursion(0, 0, 0);}bool cNQueens::Recursion(long row, long ld, long rd){ //当列禁<m_n时,说明1.棋子没摆完 | 2.棋子不能再摆放了 if (row != m_upperlim) { //得到本行可放棋子的位置 long pos = m_upperlim & ~(row | ld | rd); //当pos!=0说明本行还有棋子可以摆放 while (pos) { //pos与(pos取反再+1)得到本行最右一列棋子可摆放的位置 long p = pos & (-pos); //将pos最右可摆放位置清除以便遍历本行下一个可摆放位置 pos -= p; //更新下一行的行禁,左斜禁,右斜禁 if (Recursion(row + p, (ld + p) << 1, (rd + p) >> 1)) { int path = 0; long t = p; while (t / 2 > 0){ t = t / 2; path++; }; cout << path<<'\t' ; return true; } } } else { m_sum++; return true; } return false;}//-----------------------------------------------------------int cNQueens::GAProcess(long groupNum, short * &dad, short * &mom){ ResetSum(); if (groupNum < 2)exit(0); else if (dad == NULL || mom == NULL){ return InitPop(dad,mom,groupNum); } return GACrossVariation(dad, mom, groupNum);}int cNQueens::InitPop(short * &Dad, short * &Mom, long groupNum){ short ** group = new short*[groupNum + 1]; int i = 0; for (; i < groupNum; ++i) { group[i] = new short[m_n + 1]; } //随机初始化种群 srand((unsigned)time(NULL)); for (i = 0; i < groupNum; ++i) { for (int j = 0; j < m_n; ++j) { group[i][j] = rand() % m_n; } } //depth=1评判产生双亲,调用GAVariation //评判孩子的得分如果>父亲刷新dad[2],并把dad的值给mom,否则如果得分>母亲刷新mom[2] long gnum = groupNum; //dad{index,HigherValue} double dad[2]{-1, MINVALUE}; //mom{index,LowerValue} double mom[2]{-1, MINVALUE}; while (gnum > 0) { double score = GetFit(group[gnum - 1], 1); if (score > dad[1]) { dad[0] = gnum - 1; dad[1] = score; mom[0] = dad[0]; mom[1] = dad[1]; gnum--; continue; } if (score > mom[1]) { mom[0] = gnum - 1; mom[1] = score; } gnum -= 1; } //dad[2]和mom[2]里有了新的父母下标,刷新父母的值,深拷贝 Dad = new short[m_n + 1]; Mom = new short[m_n + 1]; for (int a = 0; a < m_n; ++a) { Dad[a] = group[(int)dad[0]][a]; Mom[a] = group[(int)mom[0]][a]; } int depth = GACrossVariation(Dad, Mom, groupNum); return depth;}int cNQueens::GACrossVariation(short * &Dad, short * &Mom, long groupNum){ short ** group = new short*[groupNum + 1]; for (int i = 0; i < groupNum; ++i) { group[i] = new short[m_n + 1]; } int iter = 1; int undone = 1; while (undone) { //根据双亲进行交叉、变异产生新种群 long gnum = groupNum; //把双亲放入种群 for (int a = 0; a<m_n; ++a) { group[gnum - 1][a] = Dad[a]; group[gnum - 2][a] = Mom[a]; } gnum -= 2; //dad{index,HigherValue} double dad[2]{-1, MINVALUE}; //mom{index,LowerValue} double mom[2]{-1, MINVALUE}; //srand((unsigned)time(NULL)); while (gnum > 0) { //在种群中随机选择[gnum,groupNum-1]父母进行交叉 int dadIndex=groupNum-(rand() % (groupNum - gnum) + 1); int momIndex = groupNum - (rand() % (groupNum - gnum) + 1); //深拷贝 for (int a = 0; a < m_n; ++a) { Dad[a] = group[dadIndex][a]; Mom[a] = group[momIndex][a]; } //交叉,随机选择交叉点 int k = rand() % m_n; //产生两个新孩子 for (int t = 0; t < m_n; t++) { //将新孩子存入group[gnum-1]和group[gnum-2] if (t < k) { group[gnum - 1][t] = Dad[t]; if (gnum>1)group[gnum - 2][t] = Mom[t]; } else { group[gnum - 1][t] = Mom[t]; if (gnum > 1)group[gnum - 2][t] = Dad[t]; } } //选择变异点变异值 double p = (rand() % 1000) / 1000.0; if (p<0.3) { k = rand() % m_n; group[gnum - 1][k] = rand() % m_n; k = rand() % m_n; if (gnum > 1)group[gnum - 2][k] = rand() % m_n; } //评判孩子的得分如果>父亲刷新dad[2],父亲的值给母亲continue,否则如果得分>母亲刷新mom[2] double score1 = GetFit(group[gnum - 1], iter); double score2=-1; if (gnum>1)score2 = GetFit(group[gnum - 2], iter); if (score1 > dad[1]) { dad[0] = gnum - 1; dad[1] = score1; mom[0] = dad[0]; mom[1] = dad[1]; if (score2 > score1) { dad[0] = gnum - 2; dad[1] = score2; mom[0] = dad[0]; mom[1] = dad[1]; } gnum -= 2; continue; } else if (score2>dad[1]) { dad[0] = gnum - 2; dad[1] = score2; mom[0] = dad[0]; mom[1] = dad[1]; gnum -= 2; continue; } else if (score1 > mom[1] || score2 > mom[1]) { if (score1 > score2) { mom[0] = gnum - 1; mom[1] = score1; } else { mom[0] = gnum - 2; mom[1] = score2; } } gnum -= 2; } //dad[2]和mom[2]里有了新的父母下标,刷新父母的值,深拷贝 for (int a = 0; a < m_n; ++a) { Dad[a] = group[(int)dad[0]][a]; Mom[a] = group[(int)mom[0]][a]; } //**group将被复用 if (GetDone(Dad) == DONE)return iter; if (iter % 100 == 1)cout << iter << endl; iter++; }}double cNQueens::GetDone(short* & map)const{ double fitQueens = 0; for (int i = 0; i < m_n; i++) { int sum = 0; //计算i和其它皇后的非攻击度.i为当前皇后行,map[i]为当前皇后列 for (int j = 0; j < m_n; j++) { if (abs(j - i) == abs(map[j] - map[i]) || i == j || map[i] == map[j])continue; sum += 1; } //非攻击度为n-1,则合法皇后数+1 if (sum == m_n - 1)fitQueens += 1; } //综合非攻击度和合法皇后数和迭代深度判断当前解的价值 if (fitQueens == m_n)fitQueens = DONE; return fitQueens;}double cNQueens::GetFit(short* & map, int depth)const{ double fitQueens = 0; int notAttack = 0; for (int i = 0; i < m_n; i++) { int sum = 0; //计算i和其它皇后的非攻击度.i为当前皇后行,map[i]为当前皇后列 for (int j = 0; j < m_n; j++) { if (abs(j - i) == abs(map[j] - map[i]) || i == j || map[i] == map[j])continue; sum += 1; } //非攻击度为n-1,则合法皇后数+1 if (sum == m_n - 1)fitQueens += 1; notAttack += sum; } //综合非攻击度和合法皇后数和迭代深度判断当前解的价值 //if (fitQueens == m_n)fitQueens = DONE; fitQueens = pow(depth, 2)*fitQueens + notAttack; return fitQueens;}//-----------------------------------------------------------int cNQueens::CSPProcess(short* & solution){ ResetSum(); return CSPSearch(solution);}int cNQueens::CSPSearch(short* & init){ //随机初始皇后在棋盘状态 srand((unsigned)time(NULL)); init = new short[m_n + 1]; //列值 int i = 0; for (; i < m_n; ++i) { //初始每列皇后的下标 init[i] = rand() % m_n; } //记录n个行方向,2n-1个右斜线方向,2n-1个左斜线方向皇后个数 short * Row = new short[m_n+1]; short * Rd = new short[2 * m_n]; short * Ld = new short[2 * m_n]; int rowIndex(0); int rIndex(0); int lIndex(0); //行值 int j(0); for (; i < m_n; ++i) { //初始化Row Rd Ld的值 j = init[i]; rowIndex = j; rIndex = m_n - 1 + i - j; lIndex = i + j; Row[rowIndex] += 1; Rd[rIndex] += 1; Ld[lIndex] += 1; } int currValue(0); int min(0); int afterMove(0); int count(0); while (!Done(Row, Rd, Ld)) { //遍历每列皇后 for (i = 0; i < m_n; ++i) { //开始下一列皇后 j = init[i]; rowIndex = j; rIndex = m_n - 1 + i - j; lIndex = i + j; min = Row[rowIndex] + Rd[rIndex] + Ld[lIndex] - 3; afterMove = j; //擦除掉这个皇后 Row[rowIndex] -= 1; Rd[rIndex] -= 1; Ld[lIndex] -= 1; //改变当前列皇后的位置 for (j = 0; j < m_n; ++j) { //获取当前列皇后在当前行时的冲突值大小 rowIndex = j; rIndex = m_n - 1 + i - j; lIndex = i + j; currValue = Row[rowIndex] + Rd[rIndex] + Ld[lIndex] - 3; if (min>currValue)continue; afterMove = j; } //将皇后放下 init[i] = j; rowIndex = j; rIndex = m_n - 1 + i - j; lIndex = i + j; Row[rowIndex] += 1; Rd[rIndex] += 1; Ld[lIndex] += 1; } ++count; } return count;}bool cNQueens::Done(short* & row, short* &rd, short* & ld){ if (m_n < 2)exit(0); short i = m_n; while (i--) { if (row[i]>1)return false; } i = 2 * m_n - 1; while (i--) { if (rd[i] > 1 || ld[i] > 1)return false; } return true;}#endif
1 0
- 罗马尼亚度假问题和N皇后问题
- 8皇后问题和N皇后问题
- 汉诺塔和N皇后问题
- n皇后问题和2n皇后问题
- N*N皇后问题
- 八皇后 n皇后 问题
- 八皇后N皇后问题
- 拉斯维加斯算法和N皇后问题
- N皇后问题
- n皇后问题
- N皇后问题
- N 皇后问题
- N皇后问题
- N皇后问题算法
- N 皇后问题
- N皇后问题
- N皇后问题
- n皇后问题
- 【关于适配】华为手机PopupWindow弹出时背景不变暗 或者 华为手机PopupWindow背景一闪一闪问题处理
- hibernate 如何使用oracle 数据库 默认值(sysdate)
- Kafka设计解析(一)- Kafka背景及架构介绍
- dataTables去掉搜索框和每页多少条框体,解决Cannot reinitialise DataTable问题
- http://blog.csdn.net/txx9010/article/details/7710739
- 罗马尼亚度假问题和N皇后问题
- Linux添加共享库路径
- iOS App 中,需要绑定微博、Twitter、Flickr 等第三方平台账号时,用 OAuth 授权
- ajax post与get
- sql 查询某一字段包含特定字符的数量
- MessageBox用法大全
- POJ 3206 Borg Maze(bfs+prim)
- 区别call() 和 .apply()
- C# 中闭包问题