算法訓練 單詞接龍

題目鏈接

錦囊

使用遞歸搜索,每次試着將一個可以加到後面的單詞加到後面,並檢查答案是不是更優。

問題描述 

  單詞接龍是一個與我們經常玩的成語接龍相類似的遊戲,現在我們已知一組單詞,且給定一個開頭的字母,要求出以這個字母開頭的最長的“龍”(每個單詞都最多在“龍”中出現兩次),在兩個單詞相連時,其重合部分合爲一部分,例如 beast和astonish,如果接成一條龍則變爲beastonish,另外相鄰的兩部分不能存在包含關係,例如at 和 atide 間不能相連。
 

#include <iostream>
#include <string>
#include <cstring>
using namespace std;
const int N = 20 + 5;
string words[N];
int g[N][N], vis[N];
void connection(const string &a,const string &b,int x,int y){
	int len = a.length();
	for(int i = 0; i < len-1; i++){ //不能有包含關係 
		bool ok = true;
		for(int j = 0; j < b.length() && j <= i; j++){
			if(a[len+j-i-1] != b[j]){
				ok = false;
				break;
			}
		}
		if(ok){
			if(i != b.length() -1) //不能有包含關係
			 	g[x][y] = i+1;
			return;
		}
	}
}

int ans = 0, n;
void solve(int u,int length){
	if(ans < length){
		ans = length;
	}
	for(int v = 0; v < n; v++){
		if(g[u][v] && vis[v] < 2){
			vis[v]++;
			solve(v,length+(int)words[v].length()-g[u][v]);
			vis[v]--;
		}
	}
}

int main(int argc, char** argv) {
	cin>> n; 
	char c;
	for(int i = 0; i < n; i++)
		cin>> words[i];
	for(int i = 0; i < n; i++)
		for(int j = 0; j < n; j++)
			connection(words[i], words[j], i , j);
	cin>> c;
	string s;
	for(int i = 0; i < n; i++){
		if(words[i][0] == c){
			vis[i]++;
			solve(i,words[i].length());
			vis[i]--;
			}
	}	
	cout<< ans << endl;
	return 0;
}

入格式 

  輸入的第一行爲一個單獨的整數n (n<=20)表示單詞數,以下n 行每行有一個單詞,輸入的最後一行爲一個單個字符,表示“龍”開頭的字母。你可以假定以此字母開頭的“龍”一定存在.

出格式 

  只需輸出以此字母開頭的最長的“龍”的長度

例輸入
  5
  at
  touch
  cheat
  choose
  tact
  a

樣例輸出

23

樣例說明

  連成的“龍”爲atoucheatactactouchoose

 

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