P1278单词游戏 题解
前言
看了看其他题解,得出了一个结论:我太菜了,根本看不懂。。。
经过自己一番瞎搞,竟然做出来了?!
0.基本变量
int n,ans=0; //ans是储存最终答案最大值
struct word //记录一个单词的基本信息
{
char begin,end; //起止字符
int size; //长度
bool vis; //是否被搜索过
word(){vis=0;} //初始化
}a[17];
1.暴搜过样例
首先,根据题意,我们很容易想到一种暴搜方案:
int dfs(int now,int num) //now:当前单词编号 num:之前的单词长度和
{
int flag=a[now].end,len=num+a[now].size,res=len;
/*
flag:储存当前单词的终止字符,用来筛选下一个单词
len:储存包括当前单词的单词长度和
res:储存经过当前单词的最佳答案
*/
a[now].vis=1; //标记
for(int i=1;i<=n;i++)
if(a[i].begin==flag&&!a[i].vis)
res=max(res,dfs(i,len)); //更新最佳答案
a[now].vis=0; //回溯
return res; //完结
}
这样,我们就愉快地得到了70分
2.优化出奇迹
为什么会超时呢?
当数据出现形如
ABBBBBA
ABBBBA
ABBBA
ABBBBBBA
ABBBA
的数据时,我们的暴搜会把每一个都搜一遍,直接达到了最高复杂度
那我们肯定不能每次选单词时都算一遍最大值,于是我们进行一个sort的预处理:
bool cmp(word a,word b){return a.size>b.size;}
sort(a+1,a+n+1,cmp);
提前按照长度从大到小排序,这样就能保证拥有同样首尾字母的单词中首先被选的一定是最长的。
当我们搜索到一个单词时,面对同样尾字母的下一个单词(首字母肯定都和当前单词的尾字母一样),最长的总比短的要好,而我们通过排序已经保证了第一个选的是最长的,所以选了一个后,相同尾字母的其他单词就都不用考虑,所以我们要做一个标记,标记char done[17],done[i]储存第
bool go_on=1;
//count是done数组的长度
for(int j=1;j<=count;j++) //遍历done数组每一个元素
if(a[i].end==done[j]) //判断此单词的尾字母在done中出现
{
go_on=0;
break;
}
和标记
if(go_on) //如果done中没有出现该尾字母,就递归搜索,并把该尾字母加入done中
{
res=max(res,dfs(i,len));
done[++count]=a[i].end;
}
哦,别忘了初始化(这个不用解释了吧)
int count=0,done[17];
for(int i=1;i<=16;i++)
done[i]='?';
这样,我们就得到了一份完整的AC代码
#include<bits/stdc++.h>
using namespace std;
int n,ans=0;
struct word
{
char begin,end;
int size;
bool vis;
word(){vis=0;}
}a[17];
bool cmp(word a,word b){return a.size>b.size;}
int dfs(int now,int num)
{
int flag=a[now].end,len=num+a[now].size,res=len;
int count=0,done[17];
for(int i=1;i<=16;i++)
done[i]='?';
a[now].vis=1;
for(int i=1;i<=n;i++)
{
if(a[i].begin==flag&&!a[i].vis)
{
bool go_on=1;
for(int j=1;j<=count;j++)
if(a[i].end==done[j])
{
go_on=0;
break;
}
if(go_on)
{
res=max(res,dfs(i,len));
done[++count]=a[i].end;
}
}
}
a[now].vis=0;
return res;
}
int main()
{
string s;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>s;
a[i].begin=s[0],
a[i].end=s[s.size()-1],
a[i].size=s.size();
}
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;i++)
{
a[i].vis=1;
ans=max(ans,dfs(i,0));
a[i].vis=0;
}
cout<<ans<<endl;
return 0;
}
完结撒花~