洛谷P1019——单词接龙(DFS暴力搜索)

https://www.luogu.org/problem/show?pid=1019#sub

题目描述

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

输入输出格式

 

输入格式:

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

输出格式:

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

输入输出样例

输入样例#1:
5
at
touch
cheat
choose
tact
a
输出样例#1:
23           (连成的“龙”为atoucheatactactouchoose)   
 1 #include<iostream>
 2 using namespace std;
 3 int n,used[20]={0},maxn=0; //n为单词数 used数组检测该单词是否已经被用多于两次(用++实现)  maxn表示最大长度
 4 string s[20],sum,x; //s字符串数组为读入单词 sum为各个情况最后所形成的龙 x为开头字母
 5 void dfs(string last){
 6     if(last.size()==1) sum=last; //将开头字母看成上一个单词 用x初始化sum
 7     bool ans=0; //表示接下来是否有符合要求的单词
 8     for(int i=0;i<n;i++){
 9         if(used[i]<2){
10             int m; //m为相同字母个数
11             for(int j=last.size()-1;j>=0;j--){ //从上一个单词的最后往前搜索
12                 if(last[j]==s[i][0]){ //当该字母与当前单词首字母相同时
13                     m=1;
14                     ans=1; //有单词可接 
15                     while(last[j+m]==s[i][m]) m++; //记录相同字母数量
16                 }
17                 if(ans&&j+m==last.size()) break; //若该字母加上相同字母数量等于原单词长度 该单词可接
18                 if(ans&&j+m!=last.size()) ans=0; //若不等 则ans恢复为0(即可能只是在上一个单词的中间出现与下一个单词相同的部分)
19             }
20             if(ans){
21                 int len=sum.size();
22                 sum+=s[i].substr(m,s[i].size()-m); //在sum后面添加s[i]字符串第m(-1+1)个位置的s[i].size()-m个字符(下一个单词相同字母后的字母)
23                 used[i]++; //使用次数增加
24                 dfs(s[i]); //下一个单词搜索
25                 ans=0; //恢复
26                 used[i]--;
27                 sum.erase(len,s[i].size()-m); //删去sum中len位置起的s[i].size()-m个字符(恢复原单词)
28             }
29         }
30     }
31     if(!ans&&sum.size()>maxn) maxn=sum.size(); //记录最大长度
32     return;
33 }
34 int main(){ //相信主程序so easy啦
35     cin>>n;
36     for(int i=0;i<n;i++) cin>>s[i];
37     cin>>x;
38     dfs(x);
39     cout<<maxn;
40     return 0;
41 }

 

转载于:https://www.cnblogs.com/YingZhixin/p/6674040.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值