P1278 单词游戏——深度优先 dfs

题目描述

Io和Ao在玩一个单词游戏。

他们轮流说出一个仅包含元音字母的单词,并且后一个单词的第一个字母必须与前一个单词的最后一个字母一致。

游戏可以从任何一个单词开始。

任何单词禁止说两遍,游戏中只能使用给定词典中含有的单词。

游戏的复杂度定义为游戏中所使用的单词长度总和。

编写程序,求出使用一本给定的词典来玩这个游戏所能达到的游戏最大可能复杂度。

输入格式

输入文件的第一行,表示一个自然数N(1≤N≤16),N表示一本字典中包含的单词数量以下的每一行包含字典中的一个单词,每一个单词是由字母A、E、I、O和U组成的一个字符串,每个单词的长度将小于等于100,所有的单词是不一样的。

输出格式

输出文件仅有一行,表示该游戏的最大可能复杂度。

输入输出样例

输入 #1

5
IOO
IUUO
AI
OIOOI
AOOI

输出 #1

16

题解
暴搜,代码有详细注释,看代码更好理解

#include
#include
#include
using namespace std;

vector<int> Graph[20];
string str[20];

int n,ans,sum,len[20];
int mark[20],use[20];

void dfs(int point,int step)
{
    if(ans==sum) return; // “剪枝”的一部分
    ans = max(ans,step);  // 每次取最大的值更新
    for(int i=0;i<Graph[point].size();i++)//遍历所有与该条串有联系的串
        if(!use[Graph[point][i]])//若该串没有使用过,则加上去
        {
            use[Graph[point][i]] = 1; // 标记该串已经被用过了
            dfs(Graph[point][i],step+len[Graph[point][i]]);
            use[Graph[point][i]] = 0;  // 用过之后还原
        }
}

int main()
{
    cin >> n;
    for(int i=0;i<n;i++)
    {
        cin >> str[i];
        sum += (len[i]=str[i].length());
    }
    for(int i=0;i<n;i++)
        for (int j = 0; j < n; j++)
            if(i!=j && str[i][len[i]-1] == str[j][0]) // 若首尾可以连接,则把着两条串联系起来
            {
                Graph[i].push_back(j);  // 把所有可以联系起来的存到一起
                mark[i] = mark[j] = true; // 代表着两条串可以连接起来
            }
    for(int i=0;i<n;i++)
        if(!mark[i]) sum -= len[i]; // 剔除所有串中和任意一条串都没有联系的串
    for(int i=0;i<n;i++)
    {
        if(!mark[i]) continue;  // 将用过的串做标记
        use[i] = 1;
        dfs(i,len[i]);
        use[i] = 0;           // 用完之后还原
        if(ans==sum) break;   // 这也是“剪枝”的一部分
    }
    cout << ans; // 输出结果
    return 0;
}

你可能感兴趣的:(深度优先DFS)