2017中兴算法挑战赛(迪杰斯特拉)

和刚刚结束的2017华为软件精英挑战赛相比,中兴的题目不难,花了两天时间随便搞了一下(其实也没多长时间,因为是周末,还打了农药),没什么意思,结果刚刚揭晓,58分,评价是“算法尚可,代码一般”,GG,写的太水,大佬莫笑~

赛题:

最强大脑中的收官蜂巢迷宫变态级挑战,相信大家都叹为观止!最强大脑收官战打响后,收视率节节攀升,就连蚁后也不时出题难为一下她的子民们。在动物世界中,称得上活地图的,除了蜜蜂,蚂蚁当仁不让。在复杂多变的蚁巢中, 蚂蚁总是能以最快、最高效的方式游历在各个储藏间(存储食物)。今天,她看完最新一期节目,又发布了一项新任务:小蚁同学,我需要玉米库的玉米,再要配点水果,去帮我找来吧。小蚁正准备出发,蚁后又说:哎呀,回来,我还没说完呢,还有若干要求如下:

1.小蚁同学,你需要尽可能以最少的花费拿到食物(附件图中路线上的数值表示每两个储物间的花费);

2.小蚁同学,你最多只能经过9个储藏间拿到食物(包含起止两个节点,多次通过同一节点按重复次数计算);

3.小蚁同学,你必须经过玉米间,水果间(附件图中标绿色节点);

4.别忘了,食蚁兽也在路上活动呢,一旦与食蚁兽相遇,性命危矣!不过小蚁微信群公告已经公布了敌人信息(附件图中标红色路段);

5.最后,千万别忘了,还有两段路是必须经过的,那里有我准备的神秘礼物等着你呢(附件图中标绿色路段)。

这下小蚁犯难了,这和它们平时找食物的集体活动规则不一样嘛,看来这次需要单独行动了。要怎么选路呢?小蚁经过一番苦思冥想,稿纸堆了一摞,啊,终于找到了!亲爱的同学们,你们能否也设计一种通用的路径搜索算法,来应对各种搜索限制条件,找到一条最优路径,顺利完成蚁后布置的任务呢?

2017中兴算法挑战赛(迪杰斯特拉)_第1张图片

注:

1、蚁巢,有若干个储藏间(附件图中圆圈表示),储藏间之间有诸多路可以到达(各储藏间拓扑图见附件);

2、节点本身通行无花费;

3、该图为无向图,可以正反两方向通行,两方向都会计费,并且花费相同;

4、起止节点分别为附件图中S点和E点。

5、最优路径:即满足限制条件的路径。


算法思路:

贪心算法求解初始解+分段求解最短路+模拟退火算法逐步寻优(实践证明,对于这个对这个问题,贪心算法求出的初始解基本接近最优解,所以说这个比赛很水啦。。。。)


源代码:

/************************************************************
 *
 * Shortest Path Search for ZTE Fantastic Algorithm
 * Author:      chyeer
 * Datetime:    2017-05-02
 * Description: multiple constrainted shortest path search
 *              based on Shortested Path Faster Algorithm and
 *              Simulated Anneling Algorithm
 *
************************************************************/

#ifndef ZTE_H
#define ZTE_H

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;

namespace pan{

    const int maxn = 1001;
    const int INF = 1<<10;
    const int MAX_LINE_LEN = 50000;

    struct edge   //edge
    {
        int to;
        int cost;
    };

    struct node
    {
        int from;
        int to;
    };

    extern vector myV[maxn];  // adjacecy list used for topo structure of graph
    extern vector constraints;  // storage for multiple constraints
    extern vector group;  // storage for combination of multiple constraints
    extern vector path;  // storage for shortest path
    extern int numNode, numEdge;  // vertexes, edges
    extern int minPath[maxn];  // shortest path
    extern int source[maxn];  // source[a]=b, the node before a is b
    extern int start, End;  // srouce node, sink node
    extern int S, E;  // Source Node: S, End Node: E
    extern bool inQ[maxn];  // in queue or not
    extern int wholeDis;  // storage of the miniCost for the shortest path
    extern int distance;  // distance between two nodes
    extern vector mustPassedNode;  // Node set that must be passed
    extern vector> forbidPassedEdge; // Edge set that can not be passed
    extern vector> mustPassedEdge;  // Edge set that must be passed

    void LoadDataFromFile(const char* filename); // load basic graph data
    void loadConstraints(); // used for adding constraints
    void inputItial();  // input data from screen
    void output(int start, int end);  // compute shortest path
    void SPFA(int start, int end);  // shortest path faster algorithm
    void greedyAlgorithmForFindingInitialSolution(vector& constraints,
            vector& group);  // greedy algorithm for finding initial solution
    void findInitialSolutionForSimulatedAnnealing(vector& constraints,
            vector& group);  // get initial solution for simulated anneling
    void simulatedAnnealingForGetNewSolution(vector& constraints,
            vector& group);  // get a new solution for simulated anneling
    void simulatedAnnealingForFindShortestPath(vector& constraints,
            vector& group);  // simulated anneling algorithm
    void findShortestPath(vector& group); // find shortest path
    void SaveDataToFile(const char* filename, const vector& path);
}

#endif // ZTE_H
/************************************************************
 *
 * Shortest Path Search for ZTE Fantastic Algorithm
 * Author:      chyeer
 * Datetime:    2017-05-02
 * Description: multiple constrainted shortest path search
 *              based on Shortested Path Faster Algorithm and
 *              Simulated Anneling Algorithm
 *
************************************************************/


#include "zte.h"
using namespace pan;

vector pan::myV[maxn];  //adjacecy list used for topo structure of graph
vector pan::constraints;   // storage for multiple constraints
vector pan::group;  // storage for combination of multiple constraints
vector pan::path;  // storage for shortest path
int pan::numNode, pan::numEdge; //vertexes, edges
int pan::minPath[maxn]; // shortest path
int pan::source[maxn];  // source[a]=b, the node before a is b
int pan::start, pan::End;  //srouce node, sink node
int pan::S, pan::E;  // Source Node: S, End Node: E
bool pan::inQ[maxn];  // in queue or not
int pan::wholeDis;  // storage of the miniCost for the shortest path
int pan::distance;  // distance between two nodes
vector pan::mustPassedNode;  // Node set that must be passed
vector> pan::forbidPassedEdge;  // Edge set that can not be passed
vector> pan::mustPassedEdge;  // Edge set that must be passed

void pan::LoadDataFromFile(const char *filename)
{
    FILE *fp = fopen(filename, "r");
    char *topo[MAX_LINE_LEN];  // Storage for all lines in file.
    if (fp == NULL)
    {
        printf("Fail to open file %s, %s.\n", filename, strerror(errno));
    }
    printf("Open file %s OK.\n", filename);

    char line[MAX_LINE_LEN + 2];
    unsigned int cnt = 0; // cnt: count line number of file.
    while (!feof(fp))
    {
        line[0] = 0;
        if (fgets(line, MAX_LINE_LEN + 2, fp) == NULL)  continue;
        if (line[0] == 0)   continue;
        topo[cnt] = (char *)malloc(MAX_LINE_LEN + 2);
        strncpy(topo[cnt], line, MAX_LINE_LEN + 2 - 1); // copy file to topo.
        topo[cnt][MAX_LINE_LEN + 1] = 0;
        cnt++;
    }
    fclose(fp);
    printf("There are %d lines in file %s.\n", cnt, filename);
    int mustVertexNum, forbidEdgeNum, mustEdgeNum;
    int index = 0;
    sscanf(topo[index], "%d%d%d%d%d", &S, &E, &mustVertexNum,
            &forbidEdgeNum, &mustEdgeNum);
    index += 2;
    int vertex;
    for(int i=0; i tmp;
    for(int i=0; i>::iterator iter;
    for(iter=forbidPassedEdge.begin(); iter!=forbidPassedEdge.end(); iter++)
    {
        vector::iterator it;
        for(it=myV[iter->first].begin(); it!=myV[iter->first].end(); it++)
        {
            if(it->to == iter->second)
            {
                //it->cost = INF;

                //delete forbid edge
                myV[iter->first].erase(it);
                //cout << it->to << " " << it->cost << endl;
                break;
            }
        }
        for(it=myV[iter->second].begin(); it!=myV[iter->second].end(); it++)
        {
            if(it->to == iter->first)
            {
                //it->cost = INF;

                // delete forbid edge
                myV[iter->second].erase(it);
                //cout << it->to << " " << it->cost << endl;
                break;
            }
        }

    }

    wholeDis = 0;

}

void pan::loadConstraints()
{
    node tmp;
    tmp.from = 14;
    tmp.to = 13;
    constraints.push_back(tmp);
    tmp.from = 12;
    tmp.to = -1;
    constraints.push_back(tmp);
    tmp.from = 7;
    tmp.to = -1;
    constraints.push_back(tmp);
    tmp.from = 4;
    tmp.to = 2;
    constraints.push_back(tmp);

    vector::iterator it;
    for(it=constraints.begin(); it!=constraints.end(); it++)
    {
        group.push_back(it->from);
        if(~it->to)
            group.push_back(it->to);
    }

#if 0
    for(size_t i=0; i& constraints,
        vector& group)
{
    size_t index_out, index_in;
    int cost = INF;
    size_t location = 0;
    for(size_t i=0; i::iterator itera;
    for(itera=constraints.begin(); itera!=constraints.end(); itera++)
    {
        group.push_back(itera->from);
        if(~itera->to)
            group.push_back(itera->to);
    }

#if 0
    for(size_t i=0; i& constraints,
        vector& group)
{
    constraints.clear();
    group.clear();
    vector::iterator iter;
    node tmp;

    for(iter=mustPassedNode.begin(); iter!=mustPassedNode.end(); iter++)
    {
        bool IN = false;
        for(size_t i=0; i>::iterator it;
    for(it=mustPassedEdge.begin(); it!=mustPassedEdge.end(); it++)
    {
        tmp.from = it->first;
        tmp.to = it->second;
        constraints.push_back(tmp);
    }

    vector::iterator itera;
    for(itera=constraints.begin(); itera!=constraints.end(); itera++)
    {
        group.push_back(itera->from);
        if(~itera->to)
            group.push_back(itera->to);
    }

    greedyAlgorithmForFindingInitialSolution(constraints, group);

#if 0
    for(size_t i=0; i";
    cout << path[path.size()-1] << endl;
#endif

}

void pan::simulatedAnnealingForGetNewSolution(vector& constraints, vector& group)
{
    group.clear();

    if(rand() % 2)
    {
        size_t index_x, index_y;
        index_x = rand() % constraints.size();
        index_y = rand() % constraints.size();
        while(index_x == index_y)
        {
            index_x = rand() % constraints.size();
            index_y = rand() % constraints.size();
        }

        swap(constraints[index_x], constraints[index_y]);
    }
    else
    {
        size_t index;
        while(1)
        {
            index = rand() % constraints.size();
            if(~constraints[index].from && ~constraints[index].to)
            {
                swap(constraints[index].from, constraints[index].to);
                break;
            }
        }
    }

    vector::iterator it;
    for(it=constraints.begin(); it!=constraints.end(); it++)
    {
        //if(rand() % 2)
        //    swap(it->from, it->to);
        if(~it->from)
            group.push_back(it->from);
        if(~it->to)
            group.push_back(it->to);
    }

#if 0
    while(!tmp.empty())
    {
        index = rand() % tmp.size();
        tmpNode = tmp[index];
        if(rand() % 2)
            swap(tmpNode.from, tmpNode.to);
        if(~tmpNode.from)
            group.push_back(tmpNode.from);
        if(~tmpNode.to)
            group.push_back(tmpNode.to);
        tmp.erase(tmp.begin()+index);
    }
#endif

#if 0
    vector::iterator iter;
    for(iter=group.begin(); iter!=group.end()-1; iter++)
    {
        cout << *iter << " ";
    }
    cout << *(group.end()-1) << endl;
#endif

}

// kernel algorithm ---- Simulated Anneling Algorithm
void pan::simulatedAnnealingForFindShortestPath(vector& constraints, vector& group)
{
    double speed = 0.9999, T = 1000, t_min = 0.001;

    struct timeval t0, t1;

    gettimeofday(&t0, NULL);

    findInitialSolutionForSimulatedAnnealing(constraints, group);  // find initial solution
    cout << "Initial cost: " << wholeDis << endl;
    int minCost = wholeDis; // cost of initial solution
    int bestCost = wholeDis;
    vector bestPath(path);
    vector tmpConstraints(constraints);
    vector bestConstraints(constraints);
    vector tmpGroup;
    vector bestGroup(group);
    int delta;

    int iteration = 0;
    while(T > t_min)
    {
        simulatedAnnealingForGetNewSolution(tmpConstraints, tmpGroup);
        constraints.assign(tmpConstraints.begin(), tmpConstraints.end());
        group.assign(tmpGroup.begin(), tmpGroup.end());
        findShortestPath(tmpGroup);
        delta = wholeDis - minCost;
        if(delta < 0)
        {
            //cout << "better: " << endl;
            tmpConstraints.assign(constraints.begin(), constraints.end());
            tmpGroup.assign(group.begin(), group.end());
            if(wholeDis < bestCost)
            {
                bestConstraints.assign(constraints.begin(), constraints.end());
                bestGroup.assign(group.begin(), group.end());
                bestCost = wholeDis;
                //cout << "bestCost: " << bestCost << endl;
            }
            minCost = wholeDis;
            //if(minCost == 13)
            //    break;
        }
        else
        {
            if((int)(exp(delta/T)*100) <= (rand() % 101))
            {
                //cout <<  "worse: " << endl;
                tmpConstraints.assign(constraints.begin(), constraints.end());
                tmpGroup.assign(group.begin(), group.end());
            }
        }
        T *= speed;
        iteration++;
        if(iteration == 10)
            break;
    }

    gettimeofday(&t1, NULL);

    double timeUse = t1.tv_sec - t0.tv_sec +
            (t1.tv_usec - t0.tv_usec)/1000000.0;

    findShortestPath(bestGroup);
    minCost = wholeDis;
    bestPath.assign(path.begin(), path.end());

#if 0
    int iteration = 100;
    while(iteration)
    {
        simulatedAnnealingForGetNewSolution(constraints, group);
        findShortestPath(group);
        //cout << "wholeDis: " << wholeDis << " " << "minCost: " << minCost << endl;
        if(wholeDis < minCost)
        {
            bestPath.assign(path.begin(), path.end());
            minCost = wholeDis;
            cout << "Cost: " << minCost << endl;
        }
        iteration--;
    }

#endif

    cout << "The minimum cost is: " << minCost << endl;
    cout << "Total vertex num: " << bestPath.size() << endl;
    cout << "The best path is:  ";
    vector::iterator it;
    for(it=bestPath.begin(); it!=bestPath.end()-1; it++)
    {
        cout << *it << "-->";
    }
    cout << *it << endl;
    //cout << "Total iteration num: " << iteration << endl;
    cout << "Time elapse: "  << timeUse << " s" << endl;
}

void pan::findShortestPath(vector& group)
{
    wholeDis = 0;
    path.clear();

    if(!group.empty())
    {
        SPFA(S, group[0]);

        for(size_t i=0; i>::iterator iter;
            for(iter=mustPassedEdge.begin(); iter!=mustPassedEdge.end(); iter++)
            {
                if(group[i] == iter->first && group[i+1] == iter->second)
                {
                    IN = true;
                    //add path when the edge must be passed
                    //path.push_back(group[i]);
                    path.push_back(group[i+1]);

                    //add cost
                    vector::iterator it;

                    for(it=myV[group[i]].begin(); it!=myV[group[i]].end(); it++)
                    {
                        if(it->to == group[i+1])
                        {
                            wholeDis += it->cost;
                            break;
                        }
                    }
                    break;
                }

                if(group[i] == iter->second && group[i+1] == iter->first)
                {
                    IN = true;
                    //add path when the edge must be passed
                    path.push_back(group[i+1]);
                    //path.push_back(group[i]);

                    //add cost
                    vector::iterator it;
                    for(it=myV[group[i+1]].begin(); it!=myV[group[i]].end(); it++)
                    {
                        if(it->to == group[i])
                        {
                            wholeDis += it->cost;
                            break;
                        }
                    }
                    break;
                }
            }
            if(!IN)
                SPFA(group[i], group[i+1]);
        }

        SPFA(group[group.size()-1], E);
    }

#if 0
    cout << "Minimum Cost: " << wholeDis << endl;
    cout << "Path: ";
    vector::iterator it;
    for(it=path.begin(); it!=path.end()-1; it++)
    {
        cout << *it << "-->";
    }
    cout << *it << endl;
#endif

}

void pan::inputItial()
{
    int i, from, to, cost;
    wholeDis = 0;
    for(i=0; i s;
        s.push(tmp);
        while(source[tmp]!=start)
        {
            tmp=source[tmp];
            s.push(tmp);
        }
        while(!s.empty())
        {
            //printf("-->%d",s.top());
            path.push_back(s.top());
            s.pop();
        }
        //printf("\n");

        //printf("Total cost : %d\n\n",minPath[end]);
        distance = minPath[end];
        wholeDis += minPath[end];
    }
}

void pan::SPFA(int start, int end)   //Shortest Path Faster Algorithm
{
    memset(inQ, false, sizeof(inQ));
    inQ[start] = true;
    for(int j=0; j myQ;
    myQ.push(start);

    int now, to, cost;
    while(!myQ.empty())
    {
        now=myQ.front();
        myQ.pop();

        for(size_t k=0; kcost)
            {
                source[to] = now;    //record the source of to: now

                minPath[to] = cost;

                if(!inQ[to])
                {
                    inQ[to] = true;
                    myQ.push(to);
                }
            }
        }

        inQ[now] = false;
    }

    output(start, end);
}

void pan::SaveDataToFile(const char *filename, const vector& path)
{
    fstream fs;
    fs.open(filename, ios_base::out);
    fs << path.size() << endl << endl;
    for(size_t i=0; i
/************************************************************
 *
 * Shortest Path Search for ZTE Fantastic Algorithm
 * Author:      chyeer
 * Datetime:    2017-05-02
 * Description: multiple constrainted shortest path search
 *              based on Shortested Path Faster Algorithm and
 *              Simulated Anneling Algorithm
 *
************************************************************/


#include "zte.h"
#include 
using namespace pan;

int main(int argc, char *argv[])
{

#if 0
    freopen("C:\\Users\\Administrator\\Desktop\\case4.txt", "r+" , stdin);
    while(scanf("%d%d",&numNode,&numEdge)==2,numNode || numEdge)
    {
        inputItial();
        while(scanf("%d%d",&start,&End)==2,start!=-1 && End!=-1)
        {
            SPFA(start, End);
        }
    }
    loadConstraints();
    findShortestPath(group);
    simulatedAnnealingForFindShortestPath(constraints, group);
#endif

    srand(time(NULL));

    //if(argc == 1)
    //    cout << "Not enough argument!" << endl;
    LoadDataFromFile("C:\\Users\\Administrator\\Desktop\\case4.txt");
    simulatedAnnealingForFindShortestPath(constraints, group);
    //findInitialSolutionForSimulatedAnnealing(constraints, group);
    //greedyAlgorithmForFindingInitialSolution(constraints, group);
    SaveDataToFile("C:\\Users\\Administrator\\Desktop\\result0.txt", path);
    system("pause");
    return 0;
}

 实验:


官网样例(18节点):必经点:2 必经边:2

运行结果:

2017中兴算法挑战赛(迪杰斯特拉)_第2张图片

样例1(100节点):必经点:10 必经边:5

运行结果:

2017中兴算法挑战赛(迪杰斯特拉)_第3张图片

样例2(300节点):必经点:30 必经边:15

运行结果:

2017中兴算法挑战赛(迪杰斯特拉)_第4张图片

样例3(1000节点):必经点:100 必经边:50

运行结果:

2017中兴算法挑战赛(迪杰斯特拉)_第5张图片


注:以上用例是ShooterIT大神提供,初写博客,太水,大佬勿喷~

你可能感兴趣的:(Informal,Essay)