【问题描述】

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

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

【数据范围】

单词长度不超过5,单词个数不超过30;


这个题算法大概是搜索,这可真的是令人质壁分离。

还记得我烤鸡写了一个多小时呀qwq(果真还是我太菜了),感觉自己代码能力真心不好呀,我可能也就for写的足够优秀了emmm。

(滚去写这个题代码了)

MY SOLUYION:
first.这个题读入就很卡人,下面我们来总结一下输入若干个(题目未给出具体的数值)应该肿么写:

  1. 输入一串长度不定的字符串

    string a;
    cin>>a;//直接用string然后cin或scanf输入就好;
  2. 今天用到的(我的写法)(自我感觉良好)
    while(ch!='\n'){
    n++;
    scanf("%s",dic[n].g);
    ch=getchar();
    }//因为输入时两个字符串之间会间隔一个空格,因此我们getchar()掉这个空格,getchar的这个空格记为ch,当ch='\n'(即说明读到了回车),那么很显然的,就不应该读下去了
  3. 之前sy讲得:(感觉我们的是差不多的嘞qwq)
    char bj=' ',i=;//bj即为标记,i为数组下标(多个数用数组比较方便)
    while(bj==' ')//因为输完数要按空格
    {cin>>a[++i];
    bj=getchar(); 一行内输入n个整数
  4. 神仙们的写法:
    //楼下捕捉一只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=;i<len;i++) dic[n+].g[i]=str[i],dic[n+].g[i]=end[i];
n+=;ss=n-;ee=n;

next.因为数据比较小嘛,所以我的想法是开一个二维数组cy(chayi)[i][j],表示第i个单词与第j个单词的差异,然后大概应该可能是用dfs计算,然后出结果;对于预处理:

  • 因为每个单词长度都不超过5,所以直接爆扫就可以了;为了看着比较简洁好看,我们写一个bj(比较)函数;二重循环(为了减少时间,我们可以把j从i+1开始循环,然后双向存储) 注意:cy[i][i]=0;(其实这个倒是也不重要因为dfs时会忽略i==j的情况)
  • 对于bj函数,返回的是第i个单词与第j个单词相差的字母数量;
    //比较函数与预处理
    int bj(char a[],char b[]){
    int c=;
    for(int i=;i<len;i++)
    if(a[i]!=b[i]) c++;
    return c;
    }
    …… for(int i=;i<=n;i++)
    for(int j=i+;j<=n;j++)
    cy[j][i]=cy[i][j]=bj(dic[i].g,dic[j].g),cy[i][i]=;

end.代码的核心dfs部分:

  1. 定义两个变量进行dfs:begin/*表示从哪个单词开始搜索下一个单词*/,ans/*记录进行了几次变换*/
  2. 在主程序中dfs(ss/*表示起点的编号*/,1/*由样例可知,str与end也要算在内,因此从1开始*/
  3. 先是临界条件:当当前dfs到的编号刚好是end的标号ee时,用f数组记录下这个解(显然dfs会搜索出所有转化情况,而我们只取最小的一种,因此要把每一种记录下来,最后sort求解)return 1(对于这个return 1是用来判断是否有解的)
  4. vis数组,用来判断某一个点是否已经搜索过
  5. 定义一个next,利用for循环找到一个与begin的差异只有1的点[如果没有显然这种情况不成立,也就是无解,因此定义一个bj=0,如果找到了差异是1的点,bj=1,在dfs的最后,如果bj=0,就说明无解,返回0],令next=i;标记vis[next]为已经搜索(1);bj=1;然后搜索(next,ans+1);记得回溯使vis[next]=0;

以上就是大致算法流程。

CODE:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string> using namespace std; char str[],end[],ch;
struct node1{
char g[];
}dic[];
int n,cy[][],len,ss,ee,ans,f[],cnt; int bj(char a[],char b[]){
int c=;
for(int i=;i<len;i++)
if(a[i]!=b[i]) c++;
return c;
}
bool vis[]; int solve(int begin,int ans){
if(begin==ee) {
f[++cnt]=ans;
return ;
}
int next;
int bj=;
for(int i=;i<=n;i++){
if(vis[i]) continue;
if(i==begin) continue;
if(cy[begin][i]!=) continue; next=i;vis[next]=;
bj=;
solve(next,ans+);
vis[next]=;
}
if(!bj) return ;
} 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=;i<len;i++) dic[n+].g[i]=str[i],dic[n+].g[i]=end[i];
n+=;ss=n-;ee=n;
for(int i=;i<=n;i++)
for(int j=i+;j<=n;j++)
cy[j][i]=cy[i][j]=bj(dic[i].g,dic[j].g),cy[i][i]=;
vis[ss]=;
if(solve(ss,)==)cout<<""<<endl;
else{
sort(f+,f+cnt+);
cout<<f[]<<endl;
}
return ;
}

然后我们看一下标程:

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[];
int vis[];
int n=;
int can(string s,string t){
if(s.size()!=t.size()) return ;
int c=;
for(int i=;i<s.size();i++)
if(s[i]!=t[i]) c++;
return c==;
}
int bfs(){
memset(vis,,sizeof(vis));
q.push((node){ss,});
while(!q.empty()){
node cur=q.front();q.pop();
if(cur.s==st) return cur.dep;//是目标
if(can(cur.s,st)) return cur.dep+;//再一步就是目标
for(int i=;i<n;i++)
if(!vis[i]&&can(cur.s,s[i])){
q.push((node){s[i],cur.dep+});
vis[i]=;
}
}
return ;
}
int main(){
freopen("word.in","r",stdin);
freopen("word.out","w",stdout);
cin>>ss>>st;
while(cin>>s[n++]);
cout<<bfs()<<endl;
return ;
}

end-

【6.12校内test】T1单词序列的更多相关文章

  1. 上午小测3 T1 括号序列 && luogu P5658 [CSP/S 2019 D1T2] 括号树 题解

    前 言: 一直很想写这道括号树..毕竟是在去年折磨了我4个小时的题.... 上午小测3 T1 括号序列 前言: 原来这题是个dp啊...这几天出了好几道dp,我都没看出来,我竟然折磨菜. 考试的时候先 ...

  2. 2021.12.06 P2501 [HAOI2006]数字序列(动态规划+LIS)

    2021.12.06 P2501 [HAOI2006]数字序列(动态规划+LIS) https://www.luogu.com.cn/problem/P2501 题意: 现在我们有一个长度为 n 的整 ...

  3. 【剑指Offer】44、反转单词序列

      题目描述:   牛客最近来了一个新员工Fish,每天早晨总是会拿着一本英文杂志,写些句子在本子上.同事Cat对Fish写的内容颇感兴趣,有一天他向Fish借来翻看,但却读不懂它的意思.例如,&qu ...

  4. 11.12模拟考T1(可持续优化)PS:神奇的东西

    1.数列操作   (array.pas/c/cpp) [问题描述] 现在有一个数列,最初包含0个数.现在要对数列操作n次,操作有3类. 1) a k,在数列的最后插入一个整数k 2) s 将最近插入的 ...

  5. 2018.08.12 bzoj5301: [Cqoi2018]异或序列(前缀和+莫队)

    传送门 简单的异或前缀和处理+莫队统计答案. 惊奇的发现无论开不开long long都能跑过... 代码: #include<bits/stdc++.h> #define N 100005 ...

  6. 18清明校内测试T1

    消失的数字(number) Time Limit:1000ms   Memory Limit:128MB 题目描述 rsy拥有n个数,这n个数分别是a1,a2,…,an. 后来出现了一个熊孩子zhw, ...

  7. 2019.7.9 校内测试 T1挖地雷

    这一次是交流测试?边交流边测试(滑稽 挖地雷 这个题是一个递推问题. 首先我们看第一个格子,因为它只影响了它的上面和右上面这两个地方是否有雷. 我们可以分3种情况讨论: 1. 第一个格子的数字是2: ...

  8. 2019.6.28 校内测试 T1 Jelly的难题1

    这题面有点难理解,建议直接跳到题意解释那一部分(虽然我觉得解释的不大对,但按照解释来做确实能AC): 按照“题意解释”的思路来思考这个题,那么就十分的简单了: 1.首先要读入这个字符矩阵,可以用cin ...

  9. 【6.12校内test】T2 子集

    这道题大概是这三道题里最简单的啦 但这阻止不了我废的脚步 [问题描述] 对于 n=4 时,对应的集合 s={4,3,2,1},他的非空子集有 15 个依次如下: {1} {2} {1,2} {3} { ...

随机推荐

  1. HTTP 请求出现 405 not allowed 的一种解决办法

    问题:http post请求网页会出现405 原因: Apache.IIS.Nginx等绝大多数web服务器,都不允许静态文件响应POST请求 解决:将post请求改为get请求

  2. 【Vue】input textarea自动滚动到输入处

    由于我这里要把接口返回的日志不断地新增到textarea里,想实现自动滚动日志的效果. 1.首先定一个textarea类型的input组件 <el-input id="textarea ...

  3. Scrapy学习(一)、Scrapy框架和数据流

    Scrapy是用python写的爬虫框架,架构图如下: 它可以分为如下七个部分: 1.Scrapy Engine:引擎,负责控制数据流在系统的所有组件中流动,并在相应动作发生时触发时间. 2.Sche ...

  4. ubuntu开启ssh服务时,报:start:Unknown job : ssh

    这里是参考网站资料,并记录下. 如图所示: 解决方法: 输入以下命令即可 /usr/sbin/sshd mkdir /var/run/sshd /usr/sbin/sshd netstat -nlt ...

  5. linux 文件目录介绍

    网上的资源 太多了,copy 过来 留给自己用吧! 摘自 : http:/ 使用linux也有一年多时间了  最近也是一直在维护网站系统主机  下面是linux目录结构说明 本人使用的是centos系 ...

  6. php的mysql语法

    php操作mysqli(示例代码) 更新时间:2013年10月28日 :: 作者: 我要评论 关注脚本之家微信公众号(jb51net) 每周都有大礼相送哦 php操作mysqli的示例代码.需要的朋友 ...

  7. Java并发编程的艺术笔记(六)——HashMap、ConcurentHashMap的原理与实现

    一.线程不安全的HashMap 多线程环境下,使用HashMap进行put操作会引起死循环(jdk1.7 Entry链表形成环形数据结构),导致CPU利用率接近100%. 结构:数组 table[]+ ...

  8. C++入门经典-例5.10-指针作为返回值

    1:代码如下: // 5.10.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <iostream> usin ...

  9. IDEA 无法自动导入相关Maven jar包

    仔细看看项目右边有个很骚的"Maven Projects"按钮,点击一下 再点击这个刷新按钮,现在知道技术为何物了吗?

  10. LeetCode 17. 电话号码的字母组合(Letter Combinations of a Phone Number)

    题目描述 给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合. 给出数字到字母的映射如下(与电话按键相同).注意 1 不对应任何字母. 示例: 输入:"23" 输出: ...