escription
给定一个r行c列的在屏幕上的“虚拟键盘”,我们需要通过“上,下,左,右,选择”5个控制键来移动屏幕上的光标来打印文本。一开始,光标在键盘的左上角,每次按方向键,光标总是跳到下一个在该方向上与当前位置不同的字符,若不存在则不移动。每次按选择键,则将光标所在位置的字符打印出来。
现在求打印给定文本(要在结尾打印换行符)的最少按键次数。
Input
第一行输入r,c(1≤r,c≤50)
接下来给出一个r*c的键盘,包括大写字母,数字,横线以及星号(星号代表Enter换行)
最后一行是要打印的文本串s,s的长度不超过10000.
Output
输出打印文本(包括结尾换行符)的最少按键次数。保证一定有解。
Sample Input
2 19
ABCDEFGHIJKLMNOPQZY
X*****************Y
AZAZ
Sample Output
19
HINT
附其余三个样例
Sample Input 1
4 7
ABCDEFG
HIJKLMN
OPQRSTU
VWXYZ**
CONTEST
Sample Output 1
30
Sample Input 2
5 20
12233445566778899000
QQWWEERRTTYYUUIIOOPP
-AASSDDFFGGHHJJKKLL*
–ZZXXCCVVBBNNMM–**
ACM-ICPC-WORLD-FINALS-2015
Sample Output 2
160
Sample Input 3
6 4
AXYB
BBBB
KLMB
OPQB
DEFB
GHI*
AB
Sample Output 3
7
因为某一个点只能往四边走,所以我们预处理出往四边走能走到的地方。
然后我们进行BFS,在BFS时,我么要进行一个优化。由于BFS的性质我们可以知道如果我们某步BFS到的点如果已经被访问过,那么肯定之前访问时走到该点的步数较少。我们记录每一步走的时候,它在我们打印出的字符上的位置,并且如果它访问过一个未访问的节点,那么也给该节点表上当前位置。那么如果一个后入点,它的位置小于先入点的位置,那么它无论如何都不可能更优,所以就不用往下继续拓展了。
而如果后入点的位置更大,那么我们就将当前点的位置赋值为后入点。通过这样的优化就可以很快的跑过了。 //目前速度bzoj第12
#include<bits/stdc++.h>
#define mp make_pair
using namespace std;
int read(){
char c;int x;while(c=getchar(),c<'0'||c>'9');x=c-'0';
while(c=getchar(),c>='0'&&c<='9') x=x*10+c-'0';return x;
}
int n,m,h,t,l,visk[55][55],visp[55][55];
pair<int,int> nxt[55][55][4];
char c[55][55],s[10005];
struct node{
int x,y,k,pa;
};
queue<node> q;
int main()
{
n=read();m=read();
register int i,j,k;
memset(visk,-1,sizeof(visk));
for(int i=1;i<=n;i++){
scanf("%s",c[i]+1);
}
scanf("%s",s+1);
l=1;while(s[l]) l++;s[l]='*';
for(i=1;i<=n;i++)
for(j=1;j<=m;j++){
char s=c[i][j];
for(k=i+1;k<=n;k++)
if(c[k][j]!=s){nxt[i][j][0]=mp(k,j);break;}
for(k=i-1;k;k--)
if(c[k][j]!=s){nxt[i][j][1]=mp(k,j);break;}
for(k=j+1;k<=m;k++)
if(c[i][k]!=s){nxt[i][j][2]=mp(i,k);break;}
for(k=j-1;k;k--)
if(c[i][k]!=s){nxt[i][j][3]=mp(i,k);break;}
}
q.push((node){1,1,0,0});
while(!q.empty()){
node e=q.front();q.pop();
if(c[e.x][e.y]==s[e.k+1]){
q.push((node){e.x,e.y,e.k+1,e.pa+1});
if(e.k+1==l){
printf("%d\n",e.pa+1);exit(0);
}
}
else for(i=0;i<4;i++){
pair<int,int> w=nxt[e.x][e.y][i];
int fi=w.first,se=w.second;
if(w.first==0) continue;
if(visk[fi][se]<e.k){
visk[fi][se]=e.k;
q.push((node){fi,se,e.k,e.pa+1});
}
}
}
return 0;
}
本文介绍了一种算法,用于计算在给定的虚拟键盘上打印特定文本所需的最少按键次数,包括换行符。该算法利用了BFS搜索策略并进行了优化以减少不必要的节点扩展,确保高效地找到最优解。

337

被折叠的 条评论
为什么被折叠?



