【NOIP2000】单词接龙

1018 单词接龙 2000年NOIP全国联赛普及组NOIP全国联赛提高组
时间限制: 1 s
空间限制: 128000 KB
题目等级 : 黄金 Gold

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

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

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

样例输入 Sample Input
5
at
touch
cheat
choose
tact
a

样例输出 Sample Output
23

数据范围及提示 Data Size & Hint
(连成的“龙”为atoucheatactactouchoose)

看数据范围n比较小所以可以直接搜索
注意子串最多出现两次
重叠部分不算

#include 
#include 
#include 
#include 
using namespace std;
const int MAXN = 55;
int n,ans = 0,use[MAXN];//记录每个单词使用次数 
string begin,word[MAXN];//开头字母 记录题目所给单词

bool can(string s,string m,int k){
    /*
        现在我手上有两个串
        然后我比较这两个串能不能接起来
        就是某串的前几个字母是不是和另一个串的后几个相同
        k是一个下标,代表现在手里这两个串是由原题中某两个串截取到k || 从k截取 
    */
    int lens = s.length();
    for(int i = 0;i < k; i ++)
        if(s[lens - k + i] != m[i])
            return false;//接不起来QAQ不能在一起 
    return true;
}

void add(string &s,string m,int k){//接龙 
    /*
        k是从哪里开始不一样 就是从哪里开始接龙
        字符串的优势出现了 支持+=这种类型的操作
        比如 string a = 'abc';char b = 'd';
        a += b;a = 'abcd';
        这里就是把部分m接到s上 
    */
    int lenm = m.length();
    for(int i = k; i < lenm; i ++)  s += m[i];
}

void dfs(string now){
    /*
        我现在手里有一个串
        先看这个串是不是能更新答案
        再看别的串能不能接上
        注意每个串可以用两次 
    */
    int x = now.length();
    ans = max(ans,x);
    for(int i = 1; i <= n; i ++){
        if(use[i] >= 2) continue;//用了两次了不能用了QAQ
        int zl = word[i].length();
        for(int j = 1; j <= zl; j ++){
            //枚举一下看看能从哪里开始接龙 还是根本不能在一起QAQ 
            if(can(now,word[i],j)){//如果可以 
                string temp = now;
                /*关于为什么要复制:
                    因为当前接龙不一定最优
                    比如这个样例  touch可以接cheat也可以接choose
                    看起来choose更优 然而对于整个题目 cheat更优
                    醒醒,这是搜索,不要贪心 
                */ 
                add(temp,word[i],j);
                if(temp == now) continue;//如果接龙和现在相同就算了 肯定不如不接优 
                use[i] ++;//
                dfs(temp);//从接龙之后的串继续搜 
                use[i] --; //还原 
            } 
        } 
    }
}

int main(){
    scanf("%d",&n);
    for(int i = 1; i <= n; i ++)    cin >> word[i];
    cin >> begin;//以这个字母为开头接龙 那就从它开始搜吧 
    dfs(begin); printf("%d\n",ans);
    return 0;
}

你可能感兴趣的:(===搜索===,===模板===)