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; }
退役