首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++ 8-滑动式难题解决程序非常慢

C++ 8-滑动式难题解决程序非常慢
EN

Code Review用户
提问于 2017-04-13 13:11:21
回答 1查看 413关注 0票数 3

我已经做了一个滑动拼图解决器,这是目前为8-拼图只。它的工作太慢,即使它是基于A*算法,其f分数是根据曼哈顿距离和线性冲突计算的。但它正确地解决了所有的问题。

我希望改进代码的时间和空间消耗。你能提出一些改进建议吗?

这里是一个Github链接。

代码语言:javascript
复制
#include <iostream>
#include <sstream>
#include <algorithm>
#include <string>
#include <vector>
#include <map>
#include <cmath>
#include <assert.h>

using namespace std;

vector<string> solvePuzzle(string state);
vector<string> reconstructPath(map<string, string> cameFrom, string current);
vector<string> findNeighbors(string state);
float calcfScore(string state);
string to_string(int i);

int main() {

    // For Testing Purposes, otherwise we don't need this function

    string state;
    getline(cin, state);

    vector<string> solution = solvePuzzle(state);
    cout << "Solution:" << endl;
    for (int index = 0; index < solution.size(); index++) cout << solution[index] << endl;


    return 0;
}


vector<string> solvePuzzle(string state) {

    assert (state.length() == 9);

    vector<string> frontier;
    vector<string> visited;
    map<string, string> cameFrom;

    frontier.push_back(state);


    map<string, float> fScore;
    map<string, int> gScore;
    gScore[state] = 0;

    while (frontier.size() > 0) {

        int best_choice = 0;
        float minimum = 100;

        for (int index = 0; index < frontier.size(); index++) {
            if (fScore[frontier[index]] > minimum) best_choice = index;
        }

        string curr_state = frontier[best_choice];
        frontier.erase(frontier.begin() + best_choice);
        visited.push_back(curr_state);

        // DEBUGGING

        /*
        cout << endl << curr_state << endl;// << "Visited: ";
        //for (int index = 0; index < visited.size(); index++) cout << visited[index];
        cout << endl << "Frontier: ";
        for (int index = 0; index < frontier.size(); index++) cout << frontier[index];
        cout << endl;
        */

        if (curr_state == "123456780") {
            vector<string> path = reconstructPath(cameFrom, curr_state);

            cout << "No. of fScore's Taken: " << fScore.size() << endl;

            return path;
        }


        vector<string> neighbors = findNeighbors(curr_state);

        for (unsigned int index = 0; index < neighbors.size(); index++) {

            string neighbor = neighbors[index];
            //cout << neighbor;
            if (find(visited.begin(), visited.end(), neighbor) != visited.end()) {
                    //cout << " terminated in visited." << endl;
                    continue;
            }

            if (find(frontier.begin(), frontier.end(), neighbor) == frontier.end()) {
                //cout << " " << "State not yet Visited. State inserted in Frontier." << endl;
                frontier.push_back(neighbor);

            } else if ((gScore[curr_state] + 1) >= gScore[neighbor]) {
                    //cout << " terminated due to idiotic reasons." << endl;
                    continue;
            }

            // This path is the best until now. Record it!
            cameFrom[neighbor] = curr_state;
            gScore[neighbor] = gScore[curr_state] + 1;
            fScore[neighbor] = calcfScore(neighbor) + gScore[neighbor];

        }


        // mapping >>>>>>>>>>>>>>>>>>>>>>>>>>>
        //for (std::map<string,float>::iterator it=fScore.begin(); it!=fScore.end(); ++it) {
        //    std::cout << it->first << " => " << it->second << '\n';}
        //cout << endl;
    }

    return vector<string>();

}

vector<string> reconstructPath(map<string, string> cameFrom, string current) {

    vector<string> totalPath;
    totalPath.push_back(current);

    while (cameFrom.find(current) != cameFrom.end()) {

        current = cameFrom[current];
        totalPath.insert(totalPath.begin(), current);
    }

    return totalPath;

}


float calcfScore(string state) {

    float fScore = 0;
    string finalState = "123456780";

    for (int index = 1; index < 9; index++) {
        int req_loc = finalState.find(to_string(index));
        int loc = state.find(to_string(index));
        //cout << index << req_loc << loc << endl;

        fScore += abs(req_loc % 3 - loc % 3) + abs(static_cast<int>(req_loc/3) - static_cast<int>(loc/3));

        for (int smallIndex = (index - 1 - ((index - 1) % 3)); smallIndex < (index - 1 - ((index - 1) % 3)) + 3; smallIndex++) {

            if (smallIndex == index) continue;

            if ((smallIndex < index) & (state[smallIndex] > state[index]) & (state[smallIndex] < (index - 1 - ((index - 1) % 3)) + 3)) fScore += 2;
            if ((smallIndex > index) & (state[smallIndex] < state[index]) & (state[smallIndex] > (index - 1 - ((index - 1) % 3)))) fScore += 2;

        }


    }

    return fScore;

}

vector<string> findNeighbors(string state) {

    vector<string> neighbors;
    int index = state.find('0');

    if (index % 3 < 2) {
        string temp_state = state;
        temp_state[index] = state[index + 1];
        temp_state[index + 1] = '0';
        neighbors.push_back(temp_state);
    }

    if (index % 3 > 0) {
        string temp_state = state;
        temp_state[index] = state[index - 1];
        temp_state[index - 1] = '0';
        neighbors.push_back(temp_state);
    }

    if (index > 2) {
        string temp_state = state;
        temp_state[index] = state[index - 3];
        temp_state[index - 3] = '0';
        neighbors.push_back(temp_state);
    }

    if (index < 6) {
        string temp_state = state;
        temp_state[index] = state[index + 3];
        temp_state[index + 3] = '0';
        neighbors.push_back(temp_state);
    }

    return neighbors;

}

string to_string(int i)
{
    stringstream ss;
    ss << i;
    return ss.str();
}
EN

回答 1

Code Review用户

回答已采纳

发布于 2017-04-13 14:00:04

我犯了一个非常愚蠢的错误。

在本部分:

代码语言:javascript
复制
for (int index = 0; index < frontier.size(); index++) {
            if (fScore[frontier[index]] > minimum) best_choice = index;
        }

应该是这样的:

代码语言:javascript
复制
for (int index = 0; index < frontier.size(); index++) {
            if (fScore[frontier[index]] < minimum) {
                    best_choice = index;
                    minimum = fScore[frontier[index]];
            }

        }

我在做相反的事。现在它工作得又快又好。还是谢谢你。:)

票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/160653

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档