传送门

坑很多的一题

这里要感谢crk大佬提前帮我把所有的坑都踩了一遍...233

讲一下题目的意思:

给你一个神奇的 r*c 的键盘 (r,c<=50)

上面有大写的字母,数字,' - '号 和 ' * ' 号

有一个光标在键盘上

一开始在左上角,每次可以对光标进行一次操作:

向上,向下,向左,向右 和打印当前光标所在的字符

然后给你一个字符串(保证经过一些操作后可以打出来)

问你最少要几次操作才能打出给定的字符串

坑点:

1.在键盘上可能有很多的位置是同一种字符

2.如果从当前字符向某一个方向走,下一个字符和上一个字符一样

那么就自动跳过,直到找到下一个不一样的字符,而且只算走了一步

3.最后要在键盘上多选择一个 ' * ' 字符,表示回车

4.多组数据

数据这么小,肯定考虑搜索

预处理出每个点向4个方向到达的点

字符转成数字处理

用的是广搜,注意一次只走一步

不能走完了再选(算两步)

要分开来考虑

大概就这样吧,实现起来也不难

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<map>
#include<queue>
using namespace std;
map <char,int> Map;//用map把字符转成数字
int n,m,ans;
int mp[][],xx[]={,,,-},yy[]={,,-,};//mp存键盘状态
int nex[][][][];//nex存每个点向4个方向走,走到的点的横坐标和纵坐标
inline void premap()//预处理map
{
for(int i=;i<=;i++) Map[(char)(''+i-)]=i;
for(int i=;i<=;i++) Map[(char)('A'+i)]=i+;
Map['-']=; Map['*']=;
}
inline void prenex()//预处理nex
{
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
for(int k=;k<;k++)
{
int x=i+xx[k],y=j+yy[k];
while(mp[i][j]==mp[x][y]) x+=xx[k],y+=yy[k];//如果相同就继续走
nex[i][j][k][]=x; nex[i][j][k][]=y;
}
}
struct node
{
int x,y,stp,dis;
//x,y存横纵坐标,stp存当前已经选了几个字符,dis表示进行了几次操作
};//广搜的队列里每个点的内容
int lst[],vis[][],len;
//lst存给定的字符串转成数字后的情况
//vis是记忆化数组,存走到点 i j 时选择的字符最多为多少
inline void bfs()
{
queue <node> q;//每次都重新开一个队列,如果重复用也可以,但是要注意清空
q.push( (node){,,,} );//把初始状态压入队列
while(!q.empty())
{
node u=q.front(); q.pop();
if(mp[u.x][u.y]==lst[u.stp])//如果当前光标所在的字符是当前想要的字符
{
if(u.stp==len)//如果是最后一个字符,就代表找到了最少步数
{
ans=u.dis+;//注意+1
return;
}
//否则
u.stp++; u.dis++;//选择此字符
vis[u.x][u.y]=u.stp;//更新vis
q.push(u);//重新加入队列
}
else//如果不是想要的字符
{
int x,y;
for(int k=;k<;k++)//尝试向4个方向移动
{
x=nex[u.x][u.y][k][]; y=nex[u.x][u.y][k][];
if(x<||x>n||y<||y>m) continue;//判断越界
if(vis[x][y]>=u.stp) continue;//剪枝
vis[x][y]=u.stp;
q.push( (node){x,y,u.stp,u.dis+} );//新状态加入队列
}
}
}
}
char ch[];
int main()
{
premap();
while(scanf("%d",&n)!=EOF)
{
memset(nex,,sizeof(nex));
memset(mp,,sizeof(mp));
memset(lst,,sizeof(lst));
memset(vis,-,sizeof(vis));//注意初始化
ans=;
scanf("%d",&m);
for(int i=;i<=n;i++)
{
scanf("%s",ch);
for(int j=;j<m;j++)
mp[i][j+]=Map[ch[j]];//读入键盘并转成数字
}
scanf("%s",ch); len=strlen(ch);
for(int i=;i<len;i++) lst[i]=Map[ch[i]];//读入字符串并转成数字
lst[len]=;//最后要加一个'*'号
prenex();
bfs();
cout<<ans<<endl;
}
return ;
}

UVA1714 Keyboarding的更多相关文章

  1. UVA1714 Keyboarding(bfs)

    UVA1714 Keyboarding bfs 坑点很多的一题(由于一本通的辣鸡翻译会错题意*n). 1.多组数据 2.如果某方向上没有不同字符光标不会动 我们每次预处理出每个点向四个方向下次到达的点 ...

  2. 【广搜】Keyboarding

    题目描述 给定一个r行c列的在电视上的“虚拟键盘”,通过“上,下,左,右,选择”共5个控制键,你可以移动电视屏幕上的光标来打印文本.一开始,光标在键盘的左上角,每次按方向键,光标总是跳到下一个在该方向 ...

  3. Keyboarding (bfs+预处理+判重优化)

    # #10030. 「一本通 1.4 练习 2」Keyboarding [题目描述] 给定一个 $r$ 行 $c$ 列的在电视上的"虚拟键盘",通过「上,下,左,右,选择」共 $5 ...

  4. Keyboarding(信息学奥赛一本通-T1452)

    [题目描述] 出自 World Final 2015 F. Keyboarding 给定一个 r 行 c 列的在电视上的"虚拟键盘",通过「上,下,左,右,选择」共 5 个控制键, ...

  5. Keyboarding

    题目描述 思路 一开始想先写一个bfs,目标字符串要加上一个'*',表示这是一个换行符,然后一个字母一个字母的找,每次重置一下vis数组,bfs返回的结果再加上1,表示要打印这个字母,结果第一个样例没 ...

  6. loj题目总览

    --DavidJing提供技术支持 现将今年7月份之前必须刷完的题目列举 完成度[23/34] [178/250] 第 1 章 贪心算法 √ [11/11] #10000 「一本通 1.1 例 1」活 ...

  7. Windows-universal-samples学习笔记系列三:Navigation

    Navigation Back Button Master/detail Navigation menu (XAML) Pivot Projection XHR, handling navigatio ...

  8. CSU训练分类

    √√第一部分 基础算法(#10023 除外) 第 1 章 贪心算法 √√#10000 「一本通 1.1 例 1」活动安排 √√#10001 「一本通 1.1 例 2」种树 √√#10002 「一本通 ...

  9. LOJ 一本通一句话题解系列:

    第一部分 基础算法 第 1 章 贪心算法 1):「一本通 1.1 例 1」活动安排:按照结束时间排序,然后扫一遍就可以了. 2):「一本通 1.1 例 2」种树:首先要尽量的往区间重叠的部分种树,先按 ...

随机推荐

  1. 201671010127 2016—2017—2 Java学习周结

    时间真是个最公平东西,只要能够好好地利用它,它可以为我们带来我们我们所想要的东西.学习Java已经有一周了,对于Java基础知识的认识也更进一步,对Java的兴趣也愈来愈浓.实现一个Java程序,主要 ...

  2. ueditor 1.2.6使用方法

    本文以php版本为例: 文件下载:http://ueditor.baidu.com/website/download.html 还可以自己先定义内容,然后下载,这样可以帮助我们精简不少东西. 以本地p ...

  3. Luogu 4388 付公主的矩形

    还是挺妙的. 发现对于一个$r$行$c$列的矩阵,穿过的格子数$n = r + c - gcd(r, c)$,题目中其实给定了这个$n$,要我们计算满足这个式子的$r$和$c$的个数. 发现$n$一定 ...

  4. DIY的RPM包怎么签名呢 How to sign your custom RPM package with GPG key

    https://gist.github.com/fernandoaleman/1376720  How to sign your custom RPM package with GPG key 这是文 ...

  5. JavaWeb_内省(Instrospector)

    内省是什么? 开发框架时,经常需要使用java对象的属性来封装程序的数据,每次都是用反射技术完成此类操作过于麻烦,所以sun公司开发了一套API,专门用于操作Java对象的属性. 什么是Java对象的 ...

  6. C++面试笔记--循环链表,队列,栈,堆

    之前已经学会了单链表的建立删除插入转置以及一些普通操作,双链表和单链表差不多,就是多了一个前驱指针,在许多操作中很方便,但是加了一个指针开销应该会大一些,总体上影响不大,这里开始讨论循环链表以及其他的 ...

  7. boost库thread.hpp编译警告honored已修复

    请浏览:https://svn.boost.org/trac/boost/ticket/7874 #7874: compile warning: thread.hpp:342: warning: ty ...

  8. java的import关键字的使用

    在java中如何使用Java包中自带的类呢? 方法一: 在使用时可以用Java.(包名).(方法名).(包中的类名): 例如:Java.util.Arrays.toString(某个要排序数组); 具 ...

  9. 类的继承与super()的意义以即如何写一个正确的异常类

    这些东西都是我看了许多名师课程和自己研究的成果,严禁转载,这里指出了如何正确的自己定义一个异常类并看一看sun写的java的源代码话题一:子类的构造器执行是否一定会伴随着父类的构造执行? 1.this ...

  10. c#百分比计算

    //此方法得到的百分比后小数太多,不行double percent=Convert.ToDouble(2)/Convert.ToDouble(34); string result=(percent*1 ...