2012-11-27 19 views
1

我正在開發項目歐盟程序爲了'啓蒙',而不僅僅是解決它們。我已經在80x80矩陣上使用動態程序解決了問題81,但是當我嘗試使用統一成本搜索來解決問題時,我的程序從未消失。我只想知道這個問題是否易於使用統一的成本搜索?該問題可在this link獲得。統一成本搜索項目歐勒#81

+0

我覺得應該可以用UCS解決......當你嘗試它時發生了什麼?它超時了嗎? – Mehrdad

+0

它製作的小問題,但在80×80矩陣,它只是在直到筆記本電腦的風扇開始.. – cobie

+0

我只是做了它與〜15條UCS線的Python,得到它正確的。我想你在算法中忘記了一些東西。 (你是否檢查過以確保你不重複檢查同一個節點兩次?它與DP沒有區別) – Mehrdad

回答

3

UCS絕對有效。

from Queue import PriorityQueue 
with open('matrix.txt') as f: 
    data = map(lambda s: map(int, s.strip().split(',')), f.readlines()) 
seen = set() 
pq = PriorityQueue() 
pq.put((data[0][0], 0, 0)) 
while not pq.empty(): 
    (s, i, j) = pq.get() 
    if (i, j) not in seen: 
     seen.add((i, j)) 
     if i + 1 < len(data): pq.put((s + data[i + 1][j], i + 1, j)) 
     if j + 1 < len(data[i]): pq.put((s + data[i][j + 1], i, j + 1)) 
     if i + 1 >= len(data) and j + 1 >= len(data): print s 
+0

+1非常好的解決方案! – higuaro

+0

@ h3nr1x:謝謝:) – Mehrdad

+1

終於使其工作..問題不是算法,而是數據結構。正在使用我的優先級隊列和關閉設置的列表,所以我猜測這是導致算法一直持續下去。感謝你的回答!!! – cobie

1

這裏(作爲參考)是使用在C Uniform-cost search ++溶液中,用-O2編譯需要不到一第二上的I7(沒有優化需要3秒):

#include <iostream> 
#include <fstream> 
#include <vector> 
#include <set> 
#include <algorithm> 
using namespace std; 
struct Node { 
    size_t i, j; int cost; 
    Node(size_t i, size_t j, int cost) : i(i), j(j), cost(cost) {} 
}; 
bool operator<(const Node& a, const Node& b) { return b.cost < a.cost; } 
bool operator==(const Node& a, const Node& b) { return a.i == b.i && a.j == b.j; } 

int main() { 
    const size_t SIZE = 80; 
    ifstream fis("matrix.txt"); 
    int matrix[SIZE][SIZE]; 
    char crap; 
    for (size_t i = 0; i < SIZE; i++) 
     for (size_t j = 0; j < SIZE; j++) { 
      fis >> matrix[i][j]; 
      if (j < SIZE - 1) fis >> crap; 
     } 
    vector<Node> open; 
    set<Node> closed; 
    open.push_back(Node(0, 0, matrix[0][0])); 
    make_heap(open.begin(), open.end()); 
    while (!open.empty()) { 
     Node node = open.front(); 
     pop_heap(open.begin(), open.end()); open.pop_back(); 

     if (node.i == SIZE - 1 && node.j == SIZE - 1) { 
      cout << "solution " << node.cost << endl; 
      return 0; 
     } 
     closed.insert(node); 
     Node children[] = { Node(node.i + 1, node.j, node.cost + matrix[node.i + 1][node.j]), 
          Node(node.i, node.j + 1, node.cost + matrix[node.i][node.j + 1]) }; 
     for (int k = 0; k < 2; k++) { 
      Node child = children[k]; 
      if (!closed.count(child)) { 
       vector<Node>::iterator elem = find(open.begin(), open.end(), child); 
       if (elem == open.end()) { 
        open.push_back(child); push_heap(open.begin(), open.end()); 
       } else if (child.cost < (*elem).cost) { 
        (*elem).cost = child.cost; 
        make_heap(open.begin(), open.end()); 
       } 
      } 
     } 
    } 
} 

這個解決方案因爲它將make_heap稱爲make_heap用於在重建矢量堆中的開放節點列表中進行元素替換,但不應該永久登陸並證明可以使用UCS解決問題。建議使用Project Euler問題陳述中給出的基本案例來調試解決方案。

+0

爲什麼UCS比DP要慢?或者換句話說......你指的是什麼特定的DP算法? Bellman-Ford還是別的? – Mehrdad

+0

嗯,80×80是6400個元素。這應該不會超過幾毫秒。 –

+0

@DanielFischer是的,但我打電話'在打開的列表元素置換後make_heap'和使用'set'一個'map'爲探索節點,而不是,只是爲了讓答案更短越好(我認爲它可以縮短雖然)。這個代碼可以改善,但僅僅是證明這個問題可以通過使用UCS – higuaro