我寫的N益智解算器(見http://en.wikipedia.org/wiki/Fifteen_puzzle)A *和N - 益智優化
現在我使用的是unordered_map來存儲拼圖板, 和曼哈頓距離作爲的哈希值啓發式算法,這是一個普通的DFS。
,所以我有
auto pred = [](Node * lhs, Node * rhs){ return lhs->manhattanCost_ < rhs->manhattanCost_; };
std::multiset<Node *, decltype(pred)> frontier(pred);
std::vector<Node *> explored; // holds nodes we have already explored
std::tr1::unordered_set<unsigned> frontierHashTable;
std::tr1::unordered_set<unsigned> exploredHashTable;
這個偉大的工程,其中n = 2和3 但是,它真的碰運氣對於n = 4以上。 (STL無法爲一個新節點分配內存)
我還懷疑我得到哈希衝突的unordered_set
unsigned makeHash(const Node & pNode)
{
unsigned int b = 378551;
unsigned int a = 63689;
unsigned int hash = 0;
for(std::size_t i = 0; i < pNode.data_.size(); i++)
{
hash = hash * a + pNode.data_[i];
a = a * b;
}
return hash;
}
16! = 2×10^13(可能的佈置)
2^32 = 4×10^9(在32位散列可能的散列值)
我的問題是如何能夠優化我的代碼來解決對於n = 4和n = 5? 我知道從這裏 http://kociemba.org/fifteen/fifteensolver.html
http://www.ic-net.or.jp/home/takaken/e/15pz/index.html
爲n = 4是可能小於第二平均更小。
編輯: 算法本身是在這裏:
bool NPuzzle::aStarSearch()
{
auto pred = [](Node * lhs, Node * rhs){ return lhs->manhattanCost_ < rhs->manhattanCost_; };
std::multiset<Node *, decltype(pred)> frontier(pred);
std::vector<Node *> explored; // holds nodes we have already explored
std::tr1::unordered_set<unsigned> frontierHashTable;
std::tr1::unordered_set<unsigned> exploredHashTable;
// if we are in the solved position in the first place, return true
if(initial_ == target_)
{
current_ = initial_;
return true;
}
frontier.insert(new Node(initial_)); // we are going to delete everything from the frontier later..
for(;;)
{
if(frontier.empty())
{
std::cout << "depth first search " << "cant solve!" << std::endl;
return false;
}
// remove a node from the frontier, and place it into the explored set
Node * pLeaf = *frontier.begin();
frontier.erase(frontier.begin());
explored.push_back(pLeaf);
// do the same for the hash table
unsigned hashValue = makeHash(*pLeaf);
frontierHashTable.erase(hashValue);
exploredHashTable.insert(hashValue);
std::vector<Node *> children = pLeaf->genChildren();
for(auto it = children.begin(); it != children.end(); ++it)
{
unsigned childHash = makeHash(**it);
if(inFrontierOrExplored(frontierHashTable, exploredHashTable, childHash))
{
delete *it;
}
else
{
if(**it == target_)
{
explored.push_back(*it);
current_ = **it;
// delete everything else in children
for(auto it2 = ++it; it2 != children.end(); ++it2)
delete * it2;
// delete everything in the frontier
for(auto it = frontier.begin(); it != frontier.end(); ++it)
delete *it;
// delete everything in explored
explored_.swap(explored);
for(auto it = explored.begin(); it != explored.end(); ++it)
delete *it;
return true;
}
else
{
frontier.insert(*it);
frontierHashTable.insert(childHash);
}
}
}
}
}
什麼是用盡所有的記憶? – 2012-02-07 06:10:35
因爲我之前編寫過這個程序,所以我不希望你對n = 4有任何麻煩。我不認爲它是你的散列函數。你可能在算法中做錯了什麼。檢查你是否正在終止。 – Chip 2012-02-07 06:11:20
只是一個小小的提示:你正在使用lambdas和'auto'變量和'decltype',它顯示你顯然有一個非常新的C++ 11編譯器,但你仍然使用'tr1'?您的標準庫沒有更新?否則,你可以使用'std :: unordered_map'來代替。 – 2012-02-07 06:28:59