算法训练 单词接龙

题目链接                         蓝桥杯 算法训练---------题解

锦囊

使用递归搜索,每次试着将一个可以加到后面的单词加到后面,并检查答案是不是更优。

问题描述 

  单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合部分合为一部分,例如 beast和astonish,如果接成一条龙则变为beastonish,另外相邻的两部分不能存在包含关系,例如at 和 atide 间不能相连。
分析:将能链接的单词构成图g[u][v] 表示重叠的字符数。然后遍历搜索即可。

#include 
#include 
#include 
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

 

你可能感兴趣的:(暴力搜索)