LUOGU 1278 单词游戏

题目描述

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

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

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

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

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

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

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

输出格式:

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

输入输出样例
输入样例#1:

5
IOO
IUUO
AI
OIOOI
AOOI

输出样例#1:

16

解题思路

看数据范围似乎我的搜索过不去.。。有大神过了,就写了一发记忆化搜索,因为单词配对既要考虑顺序,又要考虑哪些单词,就直接压进去就行了。f[S][x]表示选了 S状态的单词,最后一个选的是x这个单词的最大匹配,单词结尾用vector存。

代码

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<vector>

using namespace std;
const int MAXN = 17;

int n,f[1<<MAXN][MAXN],len[MAXN],ans;
char c[MAXN][105];
bool vis[MAXN];
vector<int> st[105],ed[105];

inline int dfs(int x,int S){
    if(f[S][x]) return f[S][x];
    int ret=0;bool flag=false;
    for(vector<int>::iterator it=st[c[x][len[x]]].begin();it!=st[c[x][len[x]]].end();it++){
        if(!vis[*it]){
            vis[*it]=1;
            flag=1;
            f[S][x]=max(f[S][x],dfs(*it,S|(1<<*it-1))+len[x]);
            vis[*it]=0;
        }

    }if(!flag) {f[S][x]=len[x];return len[x];}
    return f[S][x];
}

int main(){
    scanf("%d",&n);
    for(register int i=1;i<=n;i++){
        scanf("%s",c[i]+1);
        len[i]=strlen(c[i]+1);
        st[(int)c[i][1]].push_back(i);
        ed[(int)c[i][len[i]]].push_back(i);
    }
    for(register int i=1;i<=n;i++){
        memset(vis,false,sizeof(vis));
        vis[i]=1;
        ans=max(dfs(i,1<<i-1),ans);
    }
    printf("%d",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/sdfzsyq/p/9676925.html