【问题描述】node
给出两个单词(开始单词和结束单词)以及一个词典。找出从开始单词转换到结束单词, 所须要的最短转换序列。转换的规则以下:ios
一、每次只能改变一个字母c++
二、转换过程当中出现的单词(除开始单词和结束单词)必须存在于词典中算法
例如: 开始单词为:hit数组
结束单词为:cog函数
词典为:[hot,dot,dog,lot,log,mot]spa
那么一种可能的最短变换是: hit -> hot -> dot -> dog -> cog,code
因此返回的结果是序列的长度 5;blog
注意: 一、若是不能找到这种变换,则输出 0;ci
二、词典中全部单词长度同样;
三、全部的单词都由小写字母构成;
四、开始单词和结束单词能够不在词典中。
【输入文件】
共两行,第一行为开始单词和结束单词(两个单词不一样),以空格分开。第二行为若干 的单词(各不相同),以空格分隔开来,表示词典。单词长度不超过 5,单词个数不超过 30。
【输出文件】
输出转换序列的长度。
【输入样例】
hit cog
hot dot dog lot log
【输出样例】
5
【数据范围】
单词长度不超过5,单词个数不超过30;
这个题算法大概是搜索,这可真的是使人质壁分离。
还记得我烤鸡写了一个多小时呀qwq(果然仍是我太菜了),感受本身代码能力真心很差呀,我可能也就for写的足够优秀了emmm。
(滚去写这个题代码了)
MY SOLUYION:
first.这个题读入就很卡人,下面咱们来总结一下输入若干个(题目未给出具体的数值)应该肿么写:
string a; cin>>a;//直接用string而后cin或scanf输入就好;
while(ch!='\n'){ n++; scanf("%s",dic[n].g); ch=getchar(); }//由于输入时两个字符串之间会间隔一个空格,所以咱们getchar()掉这个空格,getchar的这个空格记为ch,当ch='\n'(即说明读到了回车),那么很显然的,就不该该读下去了
char bj=' ',i=1;//bj即为标记,i为数组下标(多个数用数组比较方便) while(bj==' ')//由于输完数要按空格 {cin>>a[++i]; bj=getchar(); 一行内输入n个整数
//楼下捕捉一只yjk神仙 while(cin>>s[++n]);
//好像神仙们都是这么写的,就我这种蒟蒻写的这么复杂emm
而后由于方便计算,我把str和end加入了这n个单词以后,在字典有的单词的基础上+2
//输入部分 scanf("%s",str); scanf("%s",end); len=strlen(str); while(ch!='\n'){ n++; scanf("%s",dic[n].g); ch=getchar(); } for(int i=0;i<len;i++) dic[n+1].g[i]=str[i],dic[n+2].g[i]=end[i]; n+=2;ss=n-1;ee=n;
next.由于数据比较小嘛,因此个人想法是开一个二维数组cy(chayi)[i][j],表示第i个单词与第j个单词的差别,而后大概应该多是用dfs计算,而后出结果;对于预处理:
//比较函数与预处理 int bj(char a[],char b[]){ int c=0; for(int i=0;i<len;i++) if(a[i]!=b[i]) c++; return c; } …… for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++) cy[j][i]=cy[i][j]=bj(dic[i].g,dic[j].g),cy[i][i]=0;
end.代码的核心dfs部分:
以上就是大体算法流程。
CODE:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<string> using namespace std; char str[5],end[5],ch; struct node1{ char g[5]; }dic[31]; int n,cy[35][35],len,ss,ee,ans,f[100],cnt; int bj(char a[],char b[]){ int c=0; for(int i=0;i<len;i++) if(a[i]!=b[i]) c++; return c; } bool vis[31]; int solve(int begin,int ans){ if(begin==ee) { f[++cnt]=ans; return 1; } int next; int bj=0; for(int i=1;i<=n;i++){ if(vis[i]) continue; if(i==begin) continue; if(cy[begin][i]!=1) continue; next=i;vis[next]=1; bj=1; solve(next,ans+1); vis[next]=0; } if(!bj) return 0; } int main(){ // freopen("word2.in","r",stdin); // freopen("word.out","w",stdout); scanf("%s",str); scanf("%s",end); len=strlen(str); while(ch!='\n'){ n++; scanf("%s",dic[n].g); ch=getchar(); } for(int i=0;i<len;i++) dic[n+1].g[i]=str[i],dic[n+2].g[i]=end[i]; n+=2;ss=n-1;ee=n; for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++) cy[j][i]=cy[i][j]=bj(dic[i].g,dic[j].g),cy[i][i]=0; vis[ss]=1; if(solve(ss,1)==0)cout<<"0"<<endl; else{ sort(f+1,f+cnt+1); cout<<f[1]<<endl; } return 0; }
而后咱们看一下标程:
CODE:
//加一句注释提醒本身并不想看标程,改天再看吧qwq
#include<cstdio> #include<iostream> #include<queue> #include<cstring> using namespace std; struct node{ string s; int dep; }; queue<node>q; string ss,st,s[31]; int vis[31]; int n=0; int can(string s,string t){ if(s.size()!=t.size()) return 0; int c=0; for(int i=0;i<s.size();i++) if(s[i]!=t[i]) c++; return c==1; } int bfs(){ memset(vis,0,sizeof(vis)); q.push((node){ss,1}); while(!q.empty()){ node cur=q.front();q.pop(); if(cur.s==st) return cur.dep;//是目标 if(can(cur.s,st)) return cur.dep+1;//再一步就是目标 for(int i=0;i<n;i++) if(!vis[i]&&can(cur.s,s[i])){ q.push((node){s[i],cur.dep+1}); vis[i]=1; } } return 0; } int main(){ freopen("word.in","r",stdin); freopen("word.out","w",stdout); cin>>ss>>st; while(cin>>s[n++]); cout<<bfs()<<endl; return 0; }
end-