zoukankan      html  css  js  c++  java
  • 洛谷P1019单词接龙(正向暴力递归+贪心)

    题目链接:https://www.luogu.org/problemnew/show/P1019

    这题就是搜索dfs遍历所有连接情况,找最大的。

    难点在于:重合部分的处理,怎样获取这个重合长度。

    另外,容易理解错的2点

    1.一个字符开头,必定是包含的,所以要在主函数中for一个一个找哪个单词包含了它,字符不能放在搜索函数中(搜索函数考虑的就是不包含的情况!),不然没有答案。

    2.关于重叠部分选取:

    不是所有重合的都重合起来;

    而是选最小的重合部分,单词接龙嘛,只要有一个字符尾首重合(即相同)就符合接龙的游戏规则,而且要求最长龙,必须选最小重合部分,这就是本题贪心规则。贪心没什么难的,就是容易理解错。

    如:beaaa,aaas,重合长度为1不是3;baskask,askasklp重合长度为3不是6!

     1 #include <iostream>
     2 #include <string>
     3 #include <algorithm>
     4 #include <cstdio>
     5 #include <cstring>
     6 using namespace std;
     7 typedef long long ll;
     8 typedef unsigned long long ull;
     9 const int maxn=1e3+5;
    10 const int inf=1e9;
    11 string s[maxn],be;
    12 int vis[maxn];//标记数组
    13 int n,ans;
    14 
    15 int jud(string s1,string s2)//求最小重合长度函数,例子bask,asklp跟一遍就明白
    16 {
    17     int len1=s1.length(),len2=s2.length();
    18     int f=0;
    19     for (int i=1;i<min(len1,len2);i++)//注意:小于最短的本身减1!这就把包含情况去掉了!例如ask,askl就是0,非常巧妙!
    20     {
    21         f=0;
    22         for(int j=0;j<i;j++)
    23         {
    24             if(s1[len1-i+j]!=s2[j]) { f=1; break; }
    25         }
    26 
    27         if(!f) return i;//都没有变化,符合要求了返回最小重合
    28     }
    29 
    30     return 0;
    31 }
    32 
    33 
    34 void so(string nowstr,int nowlen)
    35 {
    36     ans=max(ans,nowlen);//更新答案最长长度
    37 
    38     for(int i=1;i<=n;i++)
    39     {
    40         if(vis[i]>=2) continue;
    41         int c=jud(nowstr,s[i]);//获取重合部分长度(因该是最小重合长度就行(因为有一个字符重合就能连接上!),多了不管)
    42 
    43         if(c>0) //有重叠部分就开始(包含部分已在jud函数中考虑到删去)
    44         {
    45             vis[i]++;
    46             so(s[i],nowlen+s[i].length()-c);
    47             vis[i]--;
    48         }
    49     }
    50 }
    51 
    52 int main()
    53 {
    54     ios::sync_with_stdio(false); cin.tie(0);
    55 
    56     cin>>n;
    57     for(int i=1;i<=n;i++) cin>>s[i];
    58     cin>>be;
    59 
    60     for(int i=1;i<=n;i++)//第一个字符必包含,所以放在搜索函数外面
    61     {
    62         string st="";
    63         st+=s[i][0];//因为字符s[i][0]不能直接和字符串be直接比较所以转换一下
    64         if(st==be)
    65         {
    66             vis[i]++;
    67             so(s[i],s[i].length());
    68             vis[i]--;
    69         }
    70     }
    71 
    72     cout<<ans<<endl;
    73 
    74     return 0;
    75 }

    完。

  • 相关阅读:
    液晶显示器分辨设置,显示器分辨率设置……
    如何显示语言栏
    查看一键Ghost的备份文件
    百度空间的变迁
    CentOS U盘安装
    Linux服务器系统选择
    博客一夜回到解放前
    spark常见的transformation和action算子
    二分查找
    9:两个栈实现一个队列
  • 原文地址:https://www.cnblogs.com/redblackk/p/9745467.html
Copyright © 2011-2022 走看看