罗马尼亚度假问题和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
原创粉丝点击