DFS+BFS 變形課

題意簡述

呃……變形課上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有無通路。在空間上,可以使首尾相同的重複單詞只佔一個空間,時間上,可以減少重複搜索的可能,達到優化的效果。

新手第一篇博客,如果內容有誤,敬請諒解~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章