一道简单的dfs+贪心剪枝
单词接龙 NOIp2000
题目描述
单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合部分合为一部分,例如 beastbeast和astonishastonish,如果接成一条龙则变为beastonishbeastonish,另外相邻的两部分不能存在包含关系,例如atat 和 atideatide 间不能相连。
输入格式
输入的第一行为一个单独的整数nn (n \le 20n≤20)表示单词数,以下nn 行每行有一个单词,输入的最后一行为一个单个字符,表示“龙”开头的字母。你可以假定以此字母开头的“龙”一定存在.
输出格式
只需输出以此字母开头的最长的“龙”的长度
一开始觉得是个裸的dfs,结果被样例卡了一会儿,才发现需要贪心。
题目很简单,英语单词接龙,问龙的长度。
注意点:
1.每个单词可以用两次。
2.相邻两部分不存在包含关系。
3.最长长度。
忽略点:最长长度需要从单词末尾向前匹配,从前向后会导致前后都能接上的情况下接前面使总长度变短,后来发现这个问题懒得改顺序直接全匹配找最大值,果然被甩了个TLE。。。
代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 int n,b[21],len,max1=0; 4 string s[21]; 5 void dfs(int len,int ans) { 6 if (len > max1)max1 = len; 7 for (int i = 0; i < n; i++) { 8 if (b[i]==2)continue; 9 int flag = 0; 10 for (int k = s[ans].length()-1; k >= max(1, (int)(s[ans].length() - (s[i].length() - 1))); k--) { 11 flag = 0; 12 for (int j = 0,h=k; h < s[ans].length(); j++,h++) { 13 if (s[ans][h] != s[i][j]) { flag = -1; break; } 14 } 15 if (flag == 0) { 16 flag = s[ans].length()-k; 17 break; 18 } 19 } 20 if (flag > 0) { 21 b[i]++; 22 dfs(len + s[i].length() - flag, i); 23 b[i]--; 24 } 25 } 26 } 27 int main() { 28 ios::sync_with_stdio(false); 29 cin >> n; 30 for (int i = 0; i < n; i++) { 31 cin >> s[i]; 32 } 33 char c; 34 cin >> c; 35 for (int i = 0; i < n; i++) { 36 memset(b, 0, sizeof(b)); 37 if (s[i][0] == c) { 38 b[i] = 1; 39 dfs(s[i].length(),i); 40 b[i] = 0; 41 } 42 } 43 cout << max1 << endl; 44 return 0; 45 }

浙公网安备 33010602011771号