题目
July 6, 2021 · View on GitHub
阿兰是某机密部门的打字员,她现在接到一个任务:需要在一天之内输入几百个长度固定为6的密码。当然,她希望输入的过程中敲击键盘的总次数越少越好。
不幸的是,出于保密的需要,该部门用于输入密码的键盘是特殊设计的,键盘上没有数字键,而只有以下六个键:Swap0, Swap1, Up, Down, Left, Right,为了说明这6个键的作用,我们先定义录入区的6个位置的编号,从左至右依次为1,2,3,4,5,6。下面列出每个键的作用:
Swap0:按Swap0,光标位置不变,将光标所在位置的数字与录入区的1号位置的数字(左起第一个数字)交换。如果光标已经处在录入区的1号位置,则按Swap0键之后,录入区的数字不变;
Swap1:按Swap1,光标位置不变,将光标所在位置的数字与录入区的6号位置的数字(左起第六个数字)交换。如果光标已经处在录入区的6号位置,则按Swap1键之后,录入区的数字不变;
Up:按Up,光标位置不变,将光标所在位置的数字加1(除非该数字是9)。例如,如果光标所在位置的数字为2,按Up之后,该处的数字变为3;如果该处数字为9,则按Up之后,数字不变,光标位置也不变;
Down:按Down,光标位置不变,将光标所在位置的数字减1(除非该数字是0),如果该处数字为0,则按Down之后,数字不变,光标位置也不变;
Left:按Left,光标左移一个位置,如果光标已经在录入区的1号位置(左起第一个位置)上,则光标不动;
Right:按Right,光标右移一个位置,如果光标已经在录入区的6号位置(左起第六个位置)上,则光标不动。
当然,为了使这样的键盘发挥作用,每次录入密码之前,录入区总会随机出现一个长度为6的初始密码,而且光标固定出现在1号位置上。当巧妙地使用上述六个特殊键之后,可以得到目标密码,这时光标允许停在任何一个位置。
现在,阿兰需要你的帮助,编写一个程序,求出录入一个密码需要的最少的击键次数。
输入描述
仅一行,含有两个长度为6的数,前者为初始密码,后者为目标密码,两个密码之间用一个空格隔开。
输出描述
仅一行,含有一个正整数,为最少需要的击键次数。
输入例子
123456 654321
输出例子
11
参考答案
#include<cstdio>
#include<cmath>
#include<cstring>
#include<queue>
#include<algorithm>
#include<iostream>
#define N 10000
using namespace std;
int sign[10][6]=
{
1,0,0,0,0,0,
1,1,0,0,0,0,
1,1,1,0,0,0,
1,1,1,1,0,0,
1,1,1,1,1,0,
1,1,1,1,1,1,
1,0,0,0,0,1,
1,1,0,0,0,1,
1,1,1,0,0,1,
1,1,1,1,0,1
};
struct data
{
int num[6],st,sta,pos;
};
int vi[6][6][6][6][6][6][6][10];
int com[N][8];
char si[7],di[7];
int a[6],b[6];
int cnt;
int check(data & t)
{
return vi[t.num[0]][t.num[1]][t.num[2]][t.num[3]][t.num[4]][t.num[5]][t.pos][t.sta];
}
void gao(data & t)
{
vi[t.num[0]][t.num[1]][t.num[2]][t.num[3]][t.num[4]][t.num[5]][t.pos][t.sta]=1;
}
void bfs()
{
cnt=0;
// memset(vi,0,sizeof(vi));
queue<data>q;
data s,t;
for(int i=0;i<6;i++)
s.num[i]=i;
s.st=s.sta=s.pos=0;
q.push(s);
vi[0][1][2][3][4][5][0][0]=1;
while(!q.empty())
{
s=q.front();
q.pop();
for(int i=0;i<6;i++)
com[cnt][i]=s.num[i];
com[cnt][6]=s.sta;
com[cnt++][7]=s.st;
t=s;
t.st++;
if(t.pos>0)
{
swap(t.num[0],t.num[t.pos]);
if(!check(t))
{
gao(t);
q.push(t);
}
swap(t.num[0],t.num[t.pos]);
}
if(t.pos<5)
{
int tmp=t.sta;
t.pos++;
if(t.pos>t.sta||(t.sta>5&&t.pos>t.sta-6))
{
if(t.sta==9)
t.sta=5;
else
t.sta++;
}
if(!check(t))
{
gao(t);
q.push(t);
}
t.sta=tmp;
t.pos--;
swap(t.num[5],t.num[t.pos]);
if(t.sta<5)
{
t.sta+=6;
if(t.sta>9)
t.sta=5;
}
if(!check(t))
{
gao(t);
q.push(t);
}
}
}
}
int main()
{
bfs();
while(~scanf("%s%s",si,di))
{
for(int i=0;i<6;i++)
{
a[i]=si[i]-'0';
b[i]=di[i]-'0';
}
int ans=9999999;
for(int i=0;i<cnt;i++)
{
int st=com[i][7],j;
for(j=0;j<6;j++)
{
if(a[com[i][j]]!=b[j]&&sign[com[i][6]][j]==0)
break;
st+=abs(a[com[i][j]]-b[j]);
}
if(j==6&&st<ans)
ans=st;
}
printf("%d\n",ans);
}
return 0;
}