在字梯遊戲中,每乙個詞都是通過將字梯中的前乙個詞改變乙個字母形成的。例如,我們可以通過一系列的單字母替換將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...