字梯遊戲求解

2021-07-23 15:26:29 字數 3297 閱讀 3375

在字梯遊戲中,每乙個詞都是通過將字梯中的前乙個詞改變乙個字母形成的。例如,我們可以通過一系列的單字母替換將zero轉換成five:zero, hero, here, hire, fire, five。

這是乙個無權最短路徑問題,其中每個詞是乙個頂點,如果兩個頂點可以通過乙個字母的替換相互轉化的話,在這兩個頂點之間就有一條(雙向)邊。

//字梯遊戲

//#include

#include

#include

#include

#include

using

namespace

std;

const

int max_num = 99999;

//儲存頂點資訊

struct vertex

;int two_words_different(string a, string b, int p)//計算兩個單詞的差異,返回差異值

if (diffs == 1)

return

1; if (diffs == 0)

return

0;//兩個單詞一樣了

}else

if (abs((int)(a.size() - b.size())) == 1)//兩者正好差乙個單詞(其實這種情況不考慮的,字梯遊戲要求所有單詞一樣,這個只是擴充字梯遊戲,兩個單詞可以不一樣)

else

for (int i = 0; i < big.size() - 1; i++)

if (big.substr(1) == small)

return p;

else

return

0; }

}vector

readwords(istream &in)

return v;

}void fill_adj_weight(vector

&words, int p)}}

}void dijkstra(int s, int d, vector

& words)//分別表示兩個單詞在words中的下標,尋找從s到d的單源最短路徑

}//沒有找到滿足條件的頂點,退出演算法;已經求出s到d的最短路徑

if (max == infinity||v== d)

break;

words[v].known = true;

//更新與v相鄰所有頂點w的dist,path

for (int i = 0; i < words[v].adj.size(); i++)}}

}}//列印最短路徑

void printpath(int index, vector

v) cout

<< v[index].name;

}int main()

for (index2 = 0; index2 < words.size(); index2++)

} while (index1 >= words.size() || index2 >= words.size());

fill_adj_weight(words, p);

dijkstra(index1, index2, words);

cout

<< endl;

printpath(index2, words);

cout

<< endl;

return

0;}

fire

five

hire

here

hero

zero

hehe

shab

shac

sbac

dbac

ddac

dddd

ddad

dded

ddem

dddm

結果:

首先要把問題轉化為模型求解。這是乙個典型的無權最短路徑求解問題,其實也可以當作有權最短路徑求解問題,只是每一路的權值是1,即表示兩個單詞之間有一處字母不一樣。

怎麼轉換呢?

首先定義乙個結構體

struct vertex

;

這個結構體表示乙個單詞的資訊,它包含目的單詞到這個單詞的路徑長,該單詞的name,該單詞實現上述路徑長的最近的乙個節點path,以及改單詞是否被處理known。另外還存有兩個重要的陣列:儲存與該單詞相鄰的其他單詞,以及兩個單詞之間的不同字母個數,即weight。 這個很重要,它是建立圖的基礎。

之後是vector readwords(istream &in)函式讀取檔案流,並儲存在words陣列中,期間完成了每個單詞的known,dist,path,name的初始化。這裡有一點需要注意:

while (in >> oneline)

這個要求讀取的檔案資料,每個單詞佔一行,即單詞與單詞之間是enter間隔,否則讀取錯誤。

讀取完之後,請求輸入兩個單詞,然後判斷輸入單詞是否在words裡,如果有乙個不在,或者都不在,就重新輸入。這一步處理感覺很巧妙,可以記下來。

然後對words裡每個單詞的adj和weight進行初始化,即計算words每個元素(即每個單詞)與其他單詞是否相鄰,以及權重,這裡相鄰的定義是兩個單詞的size()一樣,並且只差乙個字母。而判斷兩個單詞之間的差異,是通過int two_words_different(string a, string b, int p)函式來實現的,當然該函式考慮情況比較多,有的地方寫的還不是邏輯特別通,不過已經實現了所需要的功能。

等初始化完每個單詞的adj和weight之後,其實相當於建立了圖。用dijkstra演算法求解即可。

注意在dijkstra求解時,終止條件為:

//沒有找到滿足條件的頂點,退出演算法;已經求出s到d的最短路徑,也退出演算法。

if (max == infinity||v== d)

break;

這個要好好理解。

之後列印出結果。

//列印最短路徑

void printpath(int index, vector

v) cout

<< v[index].name;

}

這是典型的dijkstra演算法列印模板。

上述**參考:

字梯問題 bfs python

給定兩個單詞 start,end 和乙個字典,要求找出從單詞start變化到end的最小序列。變化過程 現的中間單詞必須是字典中有的單詞,且每次只能是變化其中的乙個字母。比如start hit end cog dict hot dot dog lot log 那麼從start變化到end經過了5步,...

求解字謎遊戲問題

解決乙個流行的字謎。輸入是由一些字母和單詞的二維陣列組成。目標是趙楚字謎中的單詞,這些單詞可能是水平 垂直或沿著對角 線異任何方向放置的。例如求解下圖 圖1 1 字謎示例12 341t his2 wats 3oah g4fg dt書中給出的直觀演算法 對單詞表中的每個單詞。我們檢查每乙個有序三元組 ...

求解填字遊戲 C

在3 3個方格的方陣中填入數字1 10的某9個數字,每個方格填乙個整數,使所有相鄰兩個方格內的兩個整數之和為素數。編寫乙個程式,求出所有滿足這個要求的數字的填法。深度遍歷九宮格,符合條件的數字填上,然後不斷回溯,找出所有情況 include include using namespace std i...