codevs 1018 [noip 2000 提高] 单词接龙

题目链接:http://codevs.cn/problem/1018/

题目描述 Description

    单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合部分合为一部分,例如 beast 和 astonish,如果接成一条龙则变为 beastonish,另外相邻的两部分不能存在包含关系,例如 at 和 atide 间不能相连。

输入描述 Input Description

   输入的第一行为一个单独的整数 n(n<=20) 表示单词数,以下 n 行每行有一个单词,输入的最后一行为一个单个字符,表示“龙”开头的字母。你可以假定以此字母开头的“龙”一定存在.

输出描述 Output Description

   只需输出以此字母开头的最长的“龙”的长度


样例输入 Sample Input

5

at

touch

cheat

choose

tact

a

 

样例输出 Sample Output

23    

数据范围及提示 Data Size & Hint

(连成的“龙”为 atoucheatactactouchoose)            


一顿乱搞。。。

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cctype>
using namespace std;

const int MAXV = 30, MAXL = 1000, INF = 0x3f3f3f3f;
int d[MAXV][MAXV];
int vis[MAXV], ans, N;
char A[MAXV][MAXL], h;

void init(){
	memset(d, -1, sizeof(d));
}

void dfs(int v, int l, int depth){
	if(vis[v] > 2) return;
	ans = max(ans, l);
//	for(int i = 0; i < depth; ++i) printf("--");
//	printf("dfs in \"%s\", ans = %d\n", A[v], l, ans);
	for(int i = 0; i <= N; ++i){
		if(d[v][i] > 0){
			++vis[i];
			dfs(i, l + d[v][i], depth + 1);
			--vis[i];
		}
	}
}

int main(){
	freopen("in.txt", "r", stdin);
	
	init();
	scanf("%d", &N);
	for(int i = 1; i <= N; ++i){
		scanf("%s", A[i]);
	}
	while(!isalpha(h = getchar()));
	for(int i = 1; i <= N; ++i){
		for(int j = 1; j <= N; ++j){
			int leni = strlen(A[i]), lenj = strlen(A[j]), minlen = min(leni, lenj);
			for(int l = 1; l < minlen; ++l){
				bool flag = true;
				for(int k = 0; k < l; ++k){
					flag = flag && (A[i][leni - l + k] == A[j][k]);
				}
				if(flag){
					d[i][j] = lenj - l;
//					printf("d[%d][%d] = %d\n", i, j, d[i][j]);
					break;
				}
			}
		}
	}
	
	for(int i = 1; i <= N; ++i){
		if(h == A[i][0]){
			d[0][i] = strlen(A[i]) - 1;
		}
	}
	
	dfs(0, 1, 0);
	printf("%d\n", ans);
	return 0;
}


posted @ 2016-02-10 20:41  will7101  阅读(162)  评论(0编辑  收藏  举报