Рекурсивное решение TSP в его итеративной форме - PullRequest
1 голос
/ 09 июля 2020

У меня есть функция, которая возвращает кратчайшее возможное расстояние между n городами. AKA Проблема коммивояжера.

int tsp(int mask, int pos, int n) 
{

    if (mask == VISITED_ALL) 
    {
        return dist[pos][0];
    }
    
    int result = 2147483647;

    for (int i = 0; i < n; i++) 
    {

        if ((mask & (1 << i)) == 0) 
        {

            int new_result = dist[pos][i] + tsp(mask | (1 << i), i, n);
            result = min(result, new_result);
        }

    }

    return result;
} 

Я хотел бы преобразовать это рекурсивное решение в итеративную форму, однако я изо всех сил пытаюсь это сделать. Я следую этому руководству, в котором описывается преобразование из рекурсивного решения в итеративное с несколькими примерами https://www.codeproject.com/Articles/418776/How-to-replace-recursive-functions-using-stack-and

ЭТО то, что я пробовал, но, похоже, не работает

int tspIterative(int mask, int pos, int n)
{
    struct MyStructure
    {
        int mask;
        int pos;
        int n;

        int new_result;
        int result;

        int stage;
    };


    int retVal = 0;

    stack<MyStructure> myStack;

    MyStructure currentStruct;
    currentStruct.mask = mask;
    currentStruct.pos = pos;
    currentStruct.n = n;

    currentStruct.new_result = 0;
    currentStruct.result = 2147483647;

    currentStruct.stage = 0;

    myStack.push(currentStruct);


    while (myStack.empty() != true)
    {
        currentStruct = myStack.top();
        myStack.pop();

        switch (currentStruct.stage)
        {
        case 0:
            if (currentStruct.mask == VISITED_ALL)
            {
                retVal = dist[pos][0];
                continue;
            }
            else
            {
                currentStruct.stage = 1;
                myStack.push(currentStruct);

                for (int i = 0; i < currentStruct.n; i++)
                {
                    if ((currentStruct.mask & (1 << i)) == 0)
                    {
                        MyStructure newStruct;
                        newStruct.mask = currentStruct.mask | (1 << i);
                        newStruct.pos = i;
                        newStruct.n = currentStruct.n;

                        newStruct.result = currentStruct.result;
                        newStruct.new_result = currentStruct.new_result;

                        newStruct.stage = 0;

                        myStack.push(newStruct);
                    }
                }
                continue;
                break;

        case 1:

            for (int i = 0; i < currentStruct.n; i++)
            {

                if ((currentStruct.mask & (1 << i)) == 0)
                {
                    currentStruct.new_result = dist[currentStruct.pos][i] + retVal;
                    currentStruct.result = min(currentStruct.result, currentStruct.new_result);
                    retVal = currentStruct.result;
                }

            }
            continue;
            break;

            }

        }

        return retVal;
    }

}

1 Ответ

0 голосов
/ 15 июля 2020

Ладно, вот и разобрался. Вот мое решение, если кому-то интересно.

int tspIterative(int mask, int pos, int n)
{
    struct MyStructure
    {
        int mask;
        int pos;
        int n;

        int new_result;
        int result;

        int nextPos;

        int stage;
    };


    int retVal = 0;
    int k = 0;

    stack<MyStructure> myStack;

    MyStructure currentStruct;
    currentStruct.mask = mask;
    currentStruct.pos = pos;
    currentStruct.n = n;

    currentStruct.new_result = 0;
    currentStruct.result = 2147483647;

    currentStruct.nextPos = 0;

    currentStruct.stage = 0;

    myStack.push(currentStruct);


    while (myStack.empty() != true)
    {
        currentStruct = myStack.top();
        myStack.pop();

        switch (currentStruct.stage)
        {

        case 0:
        {
            jump:
            if (currentStruct.mask == VISITED_ALL)
            {
                retVal = dist[currentStruct.pos][0];
                continue;
            }

            else
            {
                currentStruct.stage = 1;
                myStack.push(currentStruct);

                for (int i = currentStruct.nextPos + k; i < currentStruct.n; i++)
                {
                    if ((currentStruct.mask & (1 << i)) == 0)
                    {
                        MyStructure newStruct;
                        newStruct.mask = (currentStruct.mask) | (1 << i);
                        newStruct.pos = i;
                        newStruct.n = currentStruct.n;

                        newStruct.result = 2147483647;
                        newStruct.new_result = 0;

                        newStruct.nextPos = 0;

                        newStruct.stage = 0;

                        currentStruct = myStack.top();
                        myStack.pop();
                        currentStruct.nextPos = i;
                        myStack.push(currentStruct);


                        myStack.push(newStruct);
                        break;
                    }
                }
                continue;
            }

            break;
        }
        case 1:
        {
            k = 0;
            for (int i = currentStruct.nextPos + k; i < currentStruct.n; i++)
            {

                if ((currentStruct.mask & (1 << i)) == 0)
                {
                    if (k > 0)
                    {
                        goto jump;
                    }
                    currentStruct.new_result = dist[currentStruct.pos][i] + retVal;
                    currentStruct.result = min(currentStruct.result, currentStruct.new_result);
                    retVal = currentStruct.result;
                    k = 1;
                }

            }
            continue;
            break;
        }
        }
    }


        return retVal;
}
...