• NOIP2000 单词接龙


    题三.  单词接龙                27分)

     

      问题描述   

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

             

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

             

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

             :

     输入

    5

    at

    touch

    cheat

    choose

    tact

    a

    输出

    23           (连成的“龙”为atoucheatactactouchoose)                                         

    【思路】

      回溯法。

      可以离线求出j接在i之后的重叠部分c[i][j],这样就可以把序列的尾巴u以及序列的长度len作为状态搜索,否则还要以string为状态搜索。

     【代码】

     1 #include<iostream>
     2 #include<cstring>
     3 using namespace std;
     4 
     5 const int maxn = 20+5;
     6 int n;
     7 int c[maxn][maxn];
     8 int x[maxn],A[maxn]; //标记//序列 
     9 string words[maxn];
    10 int wordslen[maxn];
    11 int ans=0;
    12 
    13 //计算a前b后的重叠长度 
    14 //substr截取字符串  
    15 int calc(string a,string b) {
    16     int lena=a.size(),lenb=b.size();
    17     int len=min(lena,lenb);
    18     for(int l=1;l<=len-1;l++) { //len-1不能包含 //且重叠部分尽量小 从小到大枚举 
    19         if(a.substr(lena-l,l)==b.substr(0,l))
    20           return l;
    21     }
    22     return 0;
    23 }
    24 
    25 void dfs(int u,int len) {
    26     ans=max(ans,len); 
    27     for(int v=0;v<n;v++) if(x[v]<2 && c[u][v]) {
    28         x[v]++;
    29         dfs(v,len+wordslen[v]-c[u][v]);
    30         x[v]--;
    31     }
    32 }
    33 int main() {
    34     ios::sync_with_stdio(false);
    35     cin>>n;
    36     for(int i=0;i<n;i++){
    37         cin>>words[i]; wordslen[i]=words[i].size();
    38     }
    39     for(int i=0;i<n;i++) for(int j=0;j<n;j++) //自己可能与自己重叠 
    40        c[i][j]=calc(words[i],words[j]);
    41     char ch; cin>>ch;
    42     for(int i=0;i<n;i++) if(words[i][0]==ch) {
    43         x[i]++; dfs(i,wordslen[i]); x[i]--;
    44     }
    45     cout<<ans;
    46     return 0;
    47 }
  • 相关阅读:
    关于Winsock编程中IO重叠的概念
    comparator接口与Comparable接口的区别
    String、StringBuffer与StringBuilder之间区别
    Oracle 中 call 和 exec的区别
    谈谈对Spring IOC的理解(转)
    常见的几种RuntimeException
    long(Long)与int(Integer)之间的转换
    ValueStack值栈和ActionContext
    Struts2执行过程解析
    Struts2的经典入门
  • 原文地址:https://www.cnblogs.com/lidaxin/p/4859572.html
Copyright © 2020-2023  润新知