P1019 单词接龙

题目描述

单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合部分合为一部分,例如 beast和astonish,如果接成一条龙则变为beastonish,另外相邻的两部分不能存在包含关系,例如at 和 atide 间不能相连。

输入输出格式

输入格式:
输入的第一行为一个单独的整数n (n<=20)表示单词数,以下n 行每行有一个单词,输入的最后一行为一个单个字符,表示“龙”开头的字母。你可以假定以此字母开头的“龙”一定存在.

输出格式:
只需输出以此字母开头的最长的“龙”的长度

输入输出样例

输入样例#1:
5
at
touch
cheat
choose
tact
a
输出样例#1:
23 (连成的“龙”为atoucheatactactouchoose)
说明

NOIp2000提高组第三题

#include<iostream>
#include<cstdio>
using namespace std;
string s[25];
int n,side[25][25],mx,vis[25];
inline string read()
{
    string ss="";
    char ch=getchar();
    while(ch=='\n'||ch=='\r'||ch==' ')
        ch=getchar();
    while(ch!='\n'&&ch!='\r')
    {
        if(ch!=' ')
            ss.push_back(ch);
        ch=getchar();
        if(ch==EOF)
            break;
    }
    return ss;
}
void calc(int i,int j)
{
    int len=s[i].length() <s[j].length()?len=s[i].length() :s[j].length();
    int k,l=0;
    while(l<len)
    {
        l++;                    //l是尾部和首部相等的长度
        for(k=0;k<l;k++)        //l从1开始,如果可以接成,那一定是最长的
            if(s[i][s[i].length()-1-k]!=s[j][l-1-k])//从后往前进行判断
                break;
        if(k==l)               //表示能接上 
        {
            side[i][j]=s[j].length() -l;
            break;  
        }
    }
    if(i>j) calc(j,i);//除去等于的情况,额。 
}
void dfs(int i,int len)
{
    if(len>mx)
        mx=len;
    for(int j=0;j<n;j++)
    {
        if(side[i][j]>0 && vis[j]<2)
        {
            vis[j]++;
            dfs(j,len+side[i][j]); //传递新的长度
            vis[j]--;
        }   
    }   
} 
int main()
{
    scanf("%d",&n);
    for(int i=0;i<=n;i++)
    {
        s[i]=read();    
        for(int j=0;j<=i;j++)//循环的时候很巧妙,连接的时候包括它自己 
        {
            calc(i,j);  
        } 
    }
    dfs(n,1);
    cout<<mx<<endl;
    return 0; 
}

2
ho
hoooppp
h

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
char s[25][35];
int n,side[25][25],mx,v[25];
void cal(int i,int j)
{
    int k,len=0,l=0;
    int len1=strlen(s[i]);
    int len2=strlen(s[j]);
    len=len1<len2?len1:len2;
    while(++l<=len)//l假设首尾相同的数目 
    {
        for(k=0;k<l;k++)
        {
            if(s[i][len1-1-k]!=s[j][l-1-k])//...abc abc....
                break;
        }
        if(k==l) side[i][j]=len2-l;

    }  
}
void dfs(int t,int len)
{
    if(len>mx) {mx=len;}
    for(int i=0;i<n;i++)
    {
        if(side[t][i]>0 && v[i]<2)
        {
            v[i]++;
//          cout<<s[t]<<","<<s[i]<<","<<len<<","<<side[t][i]<<endl;
            dfs(i,len+side[t][i]);
            v[i]--;
        }   
    } 
}
int main()
{
    scanf("%d",&n);
    for(int i=0;i<=n;i++)//最后一个是龙的开头 
    {
        scanf("%s",s[i]);
        for(int j=0;j<=i;j++)
        {
            cal(i,j);
            if(i!=j) cal(j,i);
        }       
    }
    dfs(n,1);//龙的开头一个字母,长度为1 
    cout<<mx<<endl;
}

分部,先求首尾相同的,错误代码,如何中间输出,查找错误

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
char s[25][35];
int n,side[25][25],mx,vis[25];
void cal(int i,int j)
{
    int k,len=0;
    int len1=strlen(s[i]);
    int len2=strlen(s[j]);
    len=len1<len2?len1:len2;
    for(k=0;k<len;k++)
    {
        if(s[i][len1-1-k]!=s[j][k])
            break;
    }
    if(k==0) side[i][j]=0;//没有首尾相同的,连接值为0 
    else side[i][j]=len2-k; 
}
int main()
{
    scanf("%d",&n);
    for(int i=0;i<=n;i++)//最后一个是龙的开头 
    {
        scanf("%s",s[i]);
        for(int j=0;j<=i;j++)
        {
            cal(i,j);
            if(i!=j) cal(j,i);
            cout<<s[i]<<","<<s[j]<<","<<side[i][j]<<endl;
            cout<<s[j]<<","<<s[i]<<","<<side[j][i]<<endl;
            cout<<endl;
        }       
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值