华师一附中OI组
标题:
P1019 单词接龙
[打印本页]
作者:
admin
时间:
2018-5-11 10:47
标题:
P1019 单词接龙
https://www.luogu.org/problemnew/show/P1019
题目描述
单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合部分合为一部分,例如 beast和astonish,如果接成一条龙则变为beastonish,另外相邻的两部分不能存在包含关系,例如at 和 atide 间不能相连。
输入输出格式
输入格式:
输入的第一行为一个单独的整数n (n<=20)表示单词数,以下n 行每行有一个单词,输入的最后一行为一个单个字符,表示“龙”开头的字母。你可以假定以此字母开头的“龙”一定存在.
输出格式:
只需输出以此字母开头的最长的“龙”的长度
输入输出样例
输入样例#1:
5
at
touch
cheat
choose
tact
a
输出样例#1:
23
说明
(连成的“龙”为atoucheatactactouchoose)
NOIp2000提高组第三题
作者:
黄煦喆
时间:
2018-5-26 21:05
#include<iostream>
using namespace std;
int n;
long long ans;
string ss[21],jl;
char ch;
int b[21][21],num[21];
int cp(int i,int j)
{
int l=0,l1=ss[i].size(),l2=ss[j].size();
char ch=ss[i][l1-1];
int p=ss[j].find(ch);
if(p==0)return l2-1;
if(p==-1||p>=l1)return 0;
for(int k=p;k>=0;k--)if(ss[j][k]!=ss[i][l1-1-p+k])return 0;
return l2-p-1;
}
void ms(int k,long long s)
{
short p=0;
for(int i=1;i<=n;i++)
if(b[k][i]&&num[i]>0)
{
p++;
num[i]--;
s+=b[k][i];
int tt=ss[i].size();
ms(i,s);
num[i]++;
s-=b[k][i];
}
if(p==0)ans=max(ans,s);
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)cin>>ss[i],num[i]=2;
cin>>ch;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
b[i][j]=cp(i,j);//cout<<ss[i]<<' '<<ss[j]<<' '<<b[i][j]<<endl;}
for(int i=1;i<=n;i++)
{
int len=ss[i].size();
if(ss[i][0]==ch)
{
num[i]--;
ms(i,len);
}
}
cout<<ans;
return 0;
}
复制代码
作者:
admin
时间:
2018-5-26 21:18
17年前我的程序,2001年9月写的 ,好遥远呀!
const
maxn=20;
var
s : array[1..maxn] of string;
head : char;
best,i,n : integer;
add : array[1..maxn,1..maxn] of integer;
used : array[1..maxn] of integer;
procedure calcadd;
var
i,j,k,t,min:integer;
ok:boolean;
begin
for i:=1 to n do
for j:=1 to n do
begin
{取s[i]和s[j]中较小值}
if length(s[i])<length(s[j]) then
min:=length(s[i])
else min:=length(s[j]);
for k:=1 to min-1 do
begin
{check}
ok:=true;
for t:=1 to k do
if s[j,t]<>s[i,length(s[i])-k+t] then
begin
ok:=false;
break;
end;
{OK指能否连接上}
if ok then break;
end;
if ok then
add[i,j]:=length(s[j])-k
else
add[i,j]:=0;
end;
{计算连接后的长度}
end;
procedure search(last,len:integer);
var
i:integer;
begin
if len>best then best:=len;
for i:=1 to n do
if (add[last,i]>0)and(used[i]<2) then
begin
inc(used[i]);
search(i,len+add[last,i]);
dec(used[i]);
end;
end;
begin
readln(n);
for i:=1 to n do
readln(s[i]);
readln(head);
calcadd;
best:=0;
fillchar(used,sizeof(used),0);
for i:=1 to n do
if s[i,1]=head then
begin
used[i]:=1;
search(i,length(s[i]));
used[i]:=0;
end;
writeln(best);
end.
复制代码
作者:
admin
时间:
2018-5-26 21:27
用二维数字add[i,j]表示单词i加到单词j的后面增加的长度,0表示不能添加,这样可以预先打印出这个数组查错,运行时也可以查表获得数据,减少主程序的代码长度。
主程序就很简单了,类似2个A 2个B等的全排列,找最大值就是,基本的pmn框架。
作者:
张笑宇
时间:
2018-5-26 22:05
#include<iostream>
using namespace std;
int n,i,j,ii,c[25],ans=-1;///c字符出现次数
string s[25],ss;///s原字符 ss起点
int hb(string s1,string s2)
{
int l1=s1.size(),l2=s2.size();
for (i=1; i<=min(l1,l2)-1; i++) ///i枚举重复的长度
{
string ss1="",ss2="";
for (j=l1-i; j<=l1-1; j++)
ss1=ss1+s1[j];
for (j=0; j<=i-1; j++)
ss2=ss2+s2[j];
///cout<<ss1<<" "<<ss2<<" "<<s1<<" "<<s2<<endl;
bool bb=true;
for (j=0; j<=i-1; j++)
if (ss1[j]!=ss2[j]) bb=false;
if (bb) return i;
}
return 0;///找不到就返回0
}
void dfs(int sum,string last)
{
ans=max(ans,sum);
///cout<<ans<<endl;
for (int k=1; k<=n; k++)
{
if (c[k]>0)///还可以选择
{
int x=hb(last,s[k]);///最小公共长度
if (x>0)
{
c[k]--;
dfs(sum+s[k].size()-x,s[k]);
c[k]++;
}
}
}
}
int main()
{
cin>>n;
for (i=1; i<=n; i++) cin>>s[i],c[i]=2;
cin>>s[0];
for (ii=1;ii<=n;ii++)
{
if (s[ii][0]==s[0][0])
{
c[ii]--;
dfs(s[ii].size(),s[ii]);
for (i=1;i<=n;i++) c[i]=2;
}
}
cout<<ans;
return 0;
}
复制代码
作者:
吴语林
时间:
2018-7-30 00:04
#include <algorithm>
#include <iostream>
#include <cmath>
#include <cstring>
#include <map>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <cstdio>
#include <cstdlib>
using namespace std;
int n,vis[100]={0},all=0;
string a[100];
char qi;
void dfs(int la,int s)
{
all=max(s,all);
int lon=a[la].length();
for(int i=lon-1;i>=1;i--)
for(int j=0;j<n;j++)
if(vis[j]<=1&&a[j][0]==a[la][i]&&a[j].length()>lon-i)
{
int e=1;
for(int k=i;k<lon;k++)
if(a[la][k]!=a[j][k-i])
{
e=0;
break;
}
if(e)
{
vis[j]++;
dfs(j,s-lon+i+a[j].length());
vis[j]--;
}
}
}
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++)
cin>>a[i];
cin>>qi;
for(int i=0;i<n;i++)
if(a[i][0]==qi)
{
vis[i]++;
dfs(i,a[i].length());
vis[i]--;
}
printf("%d",all);
return 0;
}
复制代码
作者:
倚窗倾听风吹雨
时间:
2018-9-8 17:01
#include<iostream>
using namespace std;
const int M=23;
string s[M];
char ch;
int visit[M],l[M][M],ans,an;
int n;
void match(int x,int y)
{
bool b=0;
int j=0;
for(int i=s[x].size()-1;i>=0;i--)
{
for(int k=i;k<s[x].size();k++)
if(s[x][k]!=s[y][j++])
{
b=1;
break;
}
if(!b)
{
l[x][y]=s[x].size()-i;
if(l[x][y]==min(s[x].size(),s[y].size()))l[x][y]=0;
return;
}
b=0;
j=0;
}
return;
}
void dfs(int x)
{
bool flag=0;
for(int i=1;i<=n;i++)
{
if(visit[i]>=2)continue;
if(l[x][i]==0)continue;
visit[i]++;
flag=1;
an+=s[i].size()-l[x][i];
dfs(i);
an-=s[i].size()-l[x][i];
visit[i]--;
}
if(!flag)
{
ans=max(ans,an);
return;
}
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
cin>>s[i];
cin>>ch;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
match(i,j);
/// cout<<l[i][j]<<" ";
}
/// cout<<endl;
}
for(int i=1;i<=n;i++)
{
if(s[i][0]==ch)
{
visit[i]++;
an=s[i].size();
dfs(i);
an=0;
visit[i]--;
}
}
cout<<ans<<endl;
return 0;
}
复制代码
作者:
universehyf
时间:
2018-9-14 15:55
#include<iostream>
using namespace std;
int l,minl,ans=0,cc=0,n;
char ss;
string s[30];
bool b[30][30];
int c[30][30];
int bb[30];
void dfs(int x,int las)
{
for(int i=1;i<=n;i++)
if((bb[i]>0)&&(b[las][i]==1)&&(x!=1||s[i][0]==ss))
{
cc=cc+s[i].size()-c[las][i];
bb[i]--;
/*if(x==n)
{
//cout<<cc<<endl;
}*/if(cc>ans) ans=cc;
//cout<<cc;
dfs(x+1,i);
cc=cc-(s[i].size()-c[las][i]);
bb[i]++;
}
}
int main()
{
cin>>n;
for(int i=1; i<=n; i++)
cin>>s[i];
for(int i=1; i<=n; i++) bb[i]=2;
for(int i=1;i<=n;i++) {b[0][i]=1;c[0][i]=0;}
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
{
bool flag=true;l=s[i].size();
minl=min(s[i].size(),s[j].size());
for(int k=0; k<minl-1; k++)
{
if(!flag) break;
bool p=true;
for(int m=0; m<=k; m++)
{
if(s[i][l-1-k+m]!=s[j][m])
{
p=false;
break;
}
}
if(p)
{
b[i][j]=1;
c[i][j]=k+1;
flag=false;
}
}
}
/*for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
cout<<i<<" "<<j<<" ";
if(b[i][j]) cout<<'y';
else cout<<'n';
cout<<" "<<c[i][j]<<endl;
}*/
cin>>ss;
dfs(1,0);
cout<<ans;
return 0;
}
复制代码
作者:
白至白
时间:
2018-9-25 19:41
#include<iostream>
#include<cstring>
using namespace std;
int n,maxx=0;
string word[21];
int b[21];
char ch;
int check(string s1,string s2) {
int len1=s1.size(),len2=s2.size();
int k=len2>=len1?1:len1-len2;
for(int i=len1-1; i>=k ; i--)
if(s1[i]==s2[0]) {
int j;
for(j=i+1; s1[j]==s2[j-i]&&j<len1; j++);
if(j==len1) {
// cout<<"len "<<len2-len1+i<<endl;
return len2-len1+i;
}
}
return 0;
}
void dfs(string s,int sum) {
int flag=0;
for(int i=0; i<n; i++)if(b[i]) {
int che=check(s,word[i]);
if(che) {
flag=1;
// cout<<s<<' '<<word[i]<<endl;
b[i]--;
dfs(word[i],sum+che);
b[i]++;
} else continue;
}
if(flag==0) {
if(sum>maxx)maxx=sum;
return ;
}
}
int main() {
cin>>n;
for(int i=0; i<n; i++) {
b[i]=2;
cin>>word[i];
}
cin>>ch;
for(int i=0; i<n; i++)
if(word[i][0]==ch) {
b[i]--;
dfs(word[i],word[i].size());
}
cout<<maxx<<endl;
return 0;
}
复制代码
欢迎光临 华师一附中OI组 (http://hsyit.cn/)
Powered by Discuz! X3.2