题目描述:
Io和Ao在玩一个单词游戏。
他们轮流说出一个仅包含元音字母的单词,并且后一个单词的第一个字母必须与前一个单词的最后一个字母一致。
游戏可以从任何一个单词开始。
任何单词禁止说两遍 ,游戏中只能使用给定词典中含有的单词。
游戏的复杂度定义为游戏中所使用的单词长度总和。
编写程序,求出使用一本给定的词典来玩这个游戏所能达到的游戏最大可能复杂度。
输入格式 输入文件的第一行,表示一个自然数N(1≤N≤16),N表示一本字典中包含的单词数量以下的每一行包含字典中的一个单词,每一个单词是由字母A、E、I、O和U组成的一个字符串,每个单词的长度将小于等于100,所有的单词是不一样的。
输出格式 输出文件仅有一行,表示该游戏的最大可能复杂度。
输入输出样例
输入:
5
IOO
IUUO
AI
OIOOI
AOOI
输出:
16
一开始我用的爆搜,然后就没过qwq,然后我就想着可以用clock()卡一下时间看看能不能过,但没想的是竟然过了(大概数据太水了吧)下面是我写的代码爆搜的代码(后面有更加高效的方法)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<ctime>
using namespace std;
int n;
int head[27][20]={0};//head[i][j]i开头的有谁 还有数量
int s[20][3];//记录各单词的首字母和尾字母
char f[120];//输入
int h[25]={0};//记录谁被用了
int coun[27]={0};//记录各首字母的已被使用数量
int score[20];
int maxsum=0,maxn=0;
void dfc(int i,int sum)
{
if(clock()>CLOCKS_PER_SEC*0.8)//时间到达限制时间的五分之四,直接输出
{
cout<<maxsum<<endl;
exit(0);
}
int k=s[i][1]-'A';//第i个单词的尾字母
if(sum>maxsum)
maxsum=sum;
for(int j=1;j<=head[k][0];j++)//查找以k开头的单词
{
int t=head[k][j];//t为一k开头的单词下标
if(h[t]==0)//如果没有备用
{
h[t]=1;//i被使用
coun[k]++;
dfc(t,sum+score[t]);
h[t]=0;
coun[k]--;
}
}
}
int main()
{
cin>>n;
for(int i=0;i<n;i++)
{
scanf("%s",f);
s[i][0]=f[0];//记录首字母
s[i][1]=f[strlen(f)-1];//记录尾字母
score[i]=strlen(f);
maxn+=score[i];
head[f[0]-'A'][0]++;//首字母为f[0]加一
head[f[0]-'A'][head[f[0]-'A'][0]]=i;
}
for(int i=0;i<n;i++)
{
h[i]=1;
coun[s[i][0]]++;
dfc(i,score[i]);
h[i]=0;
coun[s[i][0]]--;
}
cout<<maxsum;
return 0;
}
下边的代码是用将状态用二进制来表示的,并将其的出来的数据储存在二维数组s[ I ][state]里,算是记忆化搜索(dfs)了吧,用二维数组s[i][state]而不用s[state]是因为相同的状态下其单词的连接顺序可能不同,因此用了二维数组,其中i 表示当前组成的单词最尾端是第i个单词
代码实现
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
struct node
{
char first;
char endch;
int len;
}p[20];
int s[20][1<<16]={0};//储存将各单词作为开头的所能达到最大长度
char f[102];//用于输入/
int n;
int dfs(int x,int state)
{
if(s[x][state]!=0)
return s[x][state]+p[x].len;
char ch;
ch=p[x].endch;//尾字母
for(int i=0;i<n;i++)
{
if((!((1<<(n-i-1))&state))&&(ch==p[i].first))
{
s[x][state]=max(s[x][state],dfs(i,state+(1<<(n-i-1))));
}
}
return s[x][state]+p[x].len;
}
int main()
{
int maxlen=0;
char ch;
scanf("%d%*c",&n);
for(int i=0;i<n;i++)
{
scanf("%s",f);
p[i].first=ch=f[0];//记录首字母
int k=strlen(f)-1;//尾字母的下标
p[i].endch=f[k];//尾字母
p[i].len=strlen(f);//单词的长度
}
for(int i=0;i<n;i++)
{
s[i][0]=dfs(i,1<<(n-i-1));
maxlen=max(maxlen,s[i][0]);
}
cout<<maxlen;
return 0;
}