(4.7算法之搜索)

8468:单词序列

总时间限制: 
1000ms
 
内存限制: 
1024kB
描述

给出两个单词(开始单词和结束单词)以及一个词典。找出从开始单词转换到结束单词,所需要的最短转换序列。转换的规则如下:

1、每次只能改变一个字母

2、转换过程中出现的单词(除开始单词和结束单词)必须存在于词典中

例如:

开始单词为:hit

结束单词为:cog

词典为:[hot,dot,dog,lot,log,mot]

那么一种可能的最短变换是: hit -> hot -> dot -> dog -> cog,

所以返回的结果是序列的长度5;

注意:

1、如果不能找到这种变换,则输出0;

2、词典中所有单词长度一样;

3、所有的单词都由小写字母构成;

4、开始单词和结束单词可以不在词典中。

输入
共两行,第一行为开始单词和结束单词(两个单词不同),以空格分开。第二行为若干的单词(各不相同),以空格分隔开来,表示词典。单词长度不超过5,单词个数不超过30。
输出
输出转换序列的长度。
样例输入
hit cog
hot dot dog lot log
样例输出
5


分析:
方法1:本题涉及到字符串的处理以及搜索算法。
题目求最短转换序列,果断采用广度优先搜索算法。

代码:
#include<iostream>
#include<cstring>
using namespace std;
string s0,s1,s[50];
int n=1;
struct node{
    string ss;
    int step;
}q[300];
int m,f[100]={0};//判重,即字典中的第i个单词是否出现过 
void bfs(){
    int head=0,tail=1;
    q[1].ss=s0;q[1].step=1;
    while (head<tail){
        head++;
        string s3=q[head].ss;
        int step3=q[head].step;
        f[0]=1;
        for (int i=1;i<=n;i++){
            int t=0;
            for (int j=0;j<m;j++){//第一个字符存在字符串0的位置 
            //    cout<<s3[j]<<" "<<s[i][j]<<endl;
                if(s3[j]!=s[i][j])t++;
            }
            if(t==1&&!f[i]){
                tail++;
                q[tail].ss=s[i];
                q[tail].step=step3+1;
                f[i]=1;
            //    cout<<s[i]<<" "<<step3+1<<endl;
                if(i==n) {cout<<step3+1;return ;}//如果是目标 
            }    
        }
              
   }
   cout<<0<<endl;    
}
int main(){
    cin>>s0>>s1;
    m=s0.length();//求串长 
    while(cin>>s[n])n++;
    s[n]=s1;//将目标点作为字典的最后一个单词 
    bfs();
    return 0;
}
View Code

 方法2:

本题可以使用最短路径来求解

 

建图:

开始单词为起点:0点;

结束单词为目标点:n;

字典中的单词对应得点:1~n-1

如果两个单词中只有一个字符不同,则两点之间的距离为1,否则为无穷大。

floyd算法代码:

#include<iostream>
#include<cstring>
using namespace std;
string s0,s1,s[50];
int n;
int map[300][300]={{0,0}};
struct node{
    string ss;
    int step;
}q[300];
int m,f[100]={0};//判重,即字典中的第i个单词是否出现过 
int work(string s3,string s4){
    int t=0;
    for (int j=0;j<m;j++){//第一个字符存在字符串0的位置 
        if(s3[j]!=s4[j])t++;
    }
    return t;
}
void floyd(){
    for (int k=0;k<=n;k++)
        for (int i=0;i<=n;i++)
            for(int j=0;j<=n;j++)
                if (map[i][j]>map[i][k]+map[k][j]) 
                    map[i][j]=map[i][k]+map[k][j];
}
int main(){
    cin>>s0>>s1;
    m=s0.length();//求串长 
    s[0]=s0;
    n=1;
    while(cin>>s[n])n++;
    s[n]=s1;//将目标点作为字典的最后一个单词 
    for (int i=0;i<=n;i++)
        for(int j=0;j<=n;j++)
            map[i][j]=1000000;
    for (int i=0;i<=n;i++){
        map[i][i]=1;
        for (int j=i+1;j<=n;j++)
            if (work(s[i],s[j])==1) {map[i][j]=1;map[j][i]=1;}
    }
    
    floyd();
    if (map[0][n]<1000000) cout<<map[0][n]+1;
    else cout<<0;
    return 0;
}
View Code