1019 单词接龙

难度:普及/提高-

题目类型:深搜

提交次数:5

涉及知识:深搜

题目描述

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

输入输出格式

输入格式:

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

输出格式:

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

代码:

 1 #include<iostream>
 2 #include<string>
 3 using namespace std;
 4 int n;
 5 char a[20][20];
 6 int len;
 7 int maxx=0;
 8 int visited[20];
 9 bool finished(){
10     for(int i = 1; i<=n; i++)
11         if(!visited[i]) {
12             return false;
13         }
14     return true;
15 }
16 int split(string a, string b){
17     int i;
18     int minn;
19     minn = 20;
20     if(a.length()<b.length())
21         if(a==b.substr(0, a.length())) return 0;//排除被包含情况 
22     if(a.length()>b.length())
23         if(a.substr(a.length()-b.length(),b.length())==b) return 0;
24     for(i = 1; i < a.length(); i++){
25         if(a.substr(i, a.length()-i) == b.substr(0, a.length()-i)){
26             if(a.length()-i<b.length())
27                 if(a.length()-i<minn)
28                     minn = a.length()-i;
29         }
30     }
31     if(minn == 20) return 0;
32     else return minn;
33 }
34 void dfs(int cur){
35     //if(finished()){
36       //  if(len>maxx) maxx = len;
37        //return;
38     //}
39     maxx = max(len,maxx);
40         for(int i = 1; i <= n; i++){
41             string s1 = a[cur];
42             string s2 = a[i];
43             if(visited[i]!=2&&split(s1, s2)){
44                 visited[i]++;
45                 len += s2.length()-split(s1,s2);
46                 dfs(i);
47                 len -= s2.length()-split(s1,s2);
48                 visited[i]--;
49             }
50                 
51         } 
52     
53 }
54 int main(){
55     cin>>n;
56     int i;
57     for(i = 1; i <= n; i++)
58         cin>>a[i];
59     char start;
60     cin>>start;
61     string ss;
62     for(i = 1; i <= n; i++)
63         if(a[i][0]==start){
64             ss = a[i];
65             len=ss.length();
66             visited[i] = 1;
67             dfs(i);
68             visited[i] = 0;
69         }
70     //if(n==1&&split(ss,ss)) maxx = 2*ss.length()-split(ss, ss);
71     cout<<maxx;
72     return 0;
73 }

备注:

作为一道真题实在太坑了。耗了一下午,AC了还是心情郁结。除了我自己脑残没审好题,和犯的其他错误以外,出题意图真是让人百思不得其解,不就是想考个dfs吗?

解题思路比较顺畅,结构也挺清晰的,遇到的所有问题都是细节问题。

最开始我dfs里的边界条件是一个finished函数,因为我以为每个单词都得用上。正是因为这样,加上一个单词最多可以用2次(此处是个大坑),只有一个单词时,就没法往下dfs了,也就是说envelop最长时应该是两个自己连起来,但照我那么写第一个单词就不会尝试自己连自己。后来我就把只有一个单词的情况单拎出来判断。

题目表达不清的地方:两个相邻单词不可以有包含关系,但两个一模一样的单词却可以连在一起(就是只有真子集不能连在一起),而且两个单词相接,重叠部分是可以自己任意取得?!那么就得取得越短越好了。

然后就是最让我崩溃的一个坑,不过这大概主要赖我自己审题不清。不是每一个单词都能用到!!这我tm悟了一个多小时。不过出题人的表述也脱不了干系,他说“假设龙一定存在”,正常人不应该理解成所有词都可以串接起来吗?可事实上,可以连不起来,那最大长度就是以规定字母开头最长的那个单词的长度。这样的话finished函数也卵用没有了。直接在len更新的时候更新max就行了。我注释掉的部分完全没有用了,包括把n==1的情况单拎出来也没有意义了。

这个dfs看起来怪怪的,因为它似乎没有了边界条件,接不下去的时候就停了。

总之,这一下午虽然效率低了些,应该来说还是颇有收获的。dfs掌握得大概差不多了。

可我还是鄙视这道题。

原文地址:https://www.cnblogs.com/fangziyuan/p/5875121.html