zoukankan      html  css  js  c++  java
  • 洛谷 P1019 单词接龙【经典DFS,温习搜索】

    P1019 单词接龙

    题目描述

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

    输入输出格式

    输入格式:

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

    输出格式:

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

    输入输出样例

    输入样例#1:
    5
    at
    touch
    cheat
    choose
    tact
    a
    
    输出样例#1:
    23           (连成的“龙”为atoucheatactactouchoose)   

    说明

    NOIp2000提高组第三题

    题目链接:https://www.luogu.org/problem/show?pid=1019

    分析:经典DFS,

    思路:暴力枚举每一个以给定字母开头的字符串,然后开始搜索,在搜索判断是否相重的时候可以找出当前字符串(龙)的最后一个字符

    然后再在将要比较的字符串里暴力找,如果能找到,再从当前位置往前找。如果直到将要比较的字符串全部比较完且全部相同,就加到龙里面

    易错点:

    1.可以无视题目中的at与atite的相互包含问题

    2.不要忽视自身和自身相连的情况

    3.注意龙和其长度和使用情况的初始值!!

    4.注意+1-1的边界问题!!

    详细注释在代码中已经给出,请参考代码

    下面给出AC代码:

     1 #include<bits/stdc++.h>
     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 {
     7     if(last.size()==1)
     8         sum=last; //将开头字母看成上一个单词 用x初始化sum
     9     bool ans=0; //表示接下来是否有符合要求的单词
    10     for(int i=0;i<n;i++)
    11     {
    12         if(used[i]<2)
    13         {
    14             int m; //m为相同字母个数
    15             for(int j=last.size()-1;j>=0;j--)
    16             { //从上一个单词的最后往前搜索
    17                 if(last[j]==s[i][0])
    18                 { //当该字母与当前单词首字母相同时
    19                     m=1;
    20                     ans=1; //有单词可接
    21                     while(last[j+m]==s[i][m])
    22                        m++; //记录相同字母数量
    23                 }
    24                 if(ans&&j+m==last.size())
    25                     break; //若该字母加上相同字母数量等于原单词长度 该单词可接
    26                 if(ans&&j+m!=last.size())
    27                     ans=0; //若不等 则ans恢复为0(即可能只是在上一个单词的中间出现与下一个单词相同的部分)
    28             }
    29             if(ans)
    30             {
    31                 int len=sum.size();
    32                 sum+=s[i].substr(m,s[i].size()-m); //在sum后面添加s[i]字符串第m(-1+1)个位置的s[i].size()-m个字符(下一个单词相同字母后的字母)
    33                 used[i]++; //使用次数增加
    34                 dfs(s[i]); //下一个单词搜索
    35                 ans=0; //恢复
    36                 used[i]--;
    37                 sum.erase(len,s[i].size()-m); //删去sum中len位置起的s[i].size()-m个字符(恢复原单词)
    38             }
    39         }
    40     }
    41     if(!ans&&sum.size()>maxn)
    42         maxn=sum.size(); //记录最大长度
    43     return;
    44 }
    45 int main()
    46 {
    47     cin>>n;
    48     for(int i=0;i<n;i++)
    49         cin>>s[i];
    50     cin>>x;
    51     dfs(x);
    52     cout<<maxn<<endl;
    53     return 0;
    54 }
  • 相关阅读:
    JQuery EasyUI的datagrid的使用方式总结
    重新=》easyui DataGrid是否可以动态的改变列显示的顺序
    easyui datagrid 列拖动
    MTK平台下Battery驱动分析
    Shell编程——Shell中的数学运算
    新产品为了效果,做的比較炫,用了非常多的图片和JS,所曾经端的性能是非常大的问题,分篇记录前端性能优化的一些小经验。
    iOS内存管理机制解析之MRC手动引用计数机制
    微软下一代站点开发框架:ASP.NET MVC 6 新特性揭秘
    JS简单正则得到字符串中特定的值
    数据结构和算法面试总结
  • 原文地址:https://www.cnblogs.com/ECJTUACM-873284962/p/7118210.html
Copyright © 2011-2022 走看看