題意簡述
呃……變形課上Harry碰到了一點小麻煩,因爲他並不像Hermione那樣能夠記住所有的咒語而隨意的將一個棒球變成刺蝟什麼的,但是他發現了變形咒語的一個統一規律:如果咒語是以a開頭b結尾的一個單詞,那麼它的作用就恰好是使A物體變成B物體。
Harry已經將他所會的所有咒語都列成了一個表,他想讓你幫忙計算一下他是否能完成老師的作業,將一個B(ball)變成一個M(Mouse),你知道,如果他自己不能完成的話,他就只好向Hermione請教,並且被迫聽一大堆好好學習的道理。
輸入
測試數據有多組。每組有多行,每行一個單詞,僅包括小寫字母,是Harry所會的所有咒語。數字0表示一組輸入結束。
輸出
如果Harry可以完成他的作業,就輸出“Yes.”否則就輸出“No.”(不要忽略了句號)
輸入樣例
so
soon
river
goes
them
got
moon
begin
big
0
輸出樣例
Yes.
提示
Harry可以念這個咒語:“big - got - them”.
思路
一看就知道是一道暴力 搜索題。
根據提示,若沒有直接變化的咒語,可以先把A變成B,在用另一段咒語把B變成C.用搜索方法,先從b開頭的單詞搜起,每次遍歷一遍存儲的數據,看有沒有首字母可以和當前單詞末尾字母連接的單詞,直到找到我們的m爲止。(找不到?輸“No.”呀~)
由於數據範圍一般不會很大,可以用DFS寫,但若直接用輸入的string數組去搜,未免太麻煩。
這裏定義兩個數組來分別儲存首字母和末尾字母~
char Begi_n[10101],en_d[10101];
具體代碼如下:
#include <iostream>
using namespace std;
string letter[10101];
char Begi_n[10101],en_d[10101];
//Begi_n數組儲存首字母,en_d數組儲存末尾字母
bool vis[10101]; //visit判斷是否訪問過
int t=1; //這題居然沒有單詞個數的n......
bool flag=0; //判斷是否找到
void search_dfs(int ch) { //此處搜索用的變量是單詞的下標
if(flag==1) return;
if(en_d[ch]=='m') {
cout<<"Yes."<<endl;
flag=1;
}
for(int i=1;i<=t;i++)
if(en_d[ch]==Begi_n[i] and vis[i]==false) { //判斷是否能相連且未被訪問
vis[i]=true;
search_dfs(i);
}
}
int main() {
while(cin>>letter[t]) {
t++;
while(cin>>letter[t] and letter[t]!="0") t++;
t--;
for(int i=1;i<=t;i++) {
Begi_n[i]=letter[i][0];
en_d[i]=letter[i][letter[i].length()-1];
} //輸入
for(int i=1;i<=t;i++)
if(Begi_n[i]=='b') {
vis[i]=true;
search_dfs(i);
} //找到b就進入搜索
if(flag==0) cout<<"No."<<endl;
t=1;
flag=0;
}
}
也可以用BFS來寫,用空間換時間,仍套用模板:
#include <iostream>
#include <queue>
using namespace std;
string letter[10101];
bool vis[10101];
bool flag;
int t=1;
struct node {
char begin,end;
}world[10101]; //用結構體儲存首尾字母
void search_bfs() {
queue<node>que;
node now,next;
for(int i=1;i<=t;i++) {
if(world[i].begin=='b')
que.push(world[i]);
} //首字母爲b的全扔進隊列
while(!que.empty()) {
now=que.front();
que.pop();
if(now.end=='m') { //找到m
cout<<"Yes."<<endl;
return;
}
for(int i=1;i<=t;i++)
if(world[i].begin==now.end and !vis[i]) { //能連接且未被訪問
next=world[i];
que.push(next);
vis[i]=true;
}
}
cout<<"No."<<endl; //循環結束仍未找到,輸出
return;
}
int main() {
while(cin>>letter[t]) {
t++;
while(cin>>letter[t] and letter[t]!="0") t++;
t--;
for(int i=1;i<=t;i++) {
world[i].begin=letter[i][0];
world[i].end=letter[i][letter[i].length()-1];
}
search_bfs();
t=1;
}
}
優化
在存儲數據方面,可以用圖來儲存,即26個字母中,將所有單詞的首字母和末尾字母相連一條路徑,題目即變成了尋找b和m有無通路。在空間上,可以使首尾相同的重複單詞只佔一個空間,時間上,可以減少重複搜索的可能,達到優化的效果。
新手第一篇博客,如果內容有誤,敬請諒解~