「NOIP模拟赛」聪明的打字员
聪明的打字员(typer)
阿兰是某机密部门的打字员,她现在接到一个任务:需要在一天之内输入几百个长度固定为6的密码。当然,她希望输入的过程中敲击键盘的总次数越少越好。
不幸的是,出于保密的需要,该部门用于输入密码的键盘是特殊设计的,键盘上没有数字键,而只有以下六个键:Swap0,Swap1,Up,Down,Left,Right。为了说明这6个键的
用,我们先定义录入区的6个位置的编号,从左至右依次为l,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
题解
唉直接广搜即可
常数写太丑了
状态应该表示成一个六位的数字的。。。
用六位数组存会有严重后果,不过懒得改了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
#include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> #include<cmath> #define inf 0x7fffffff #define ll long long using namespace std; inline ll read() { ll x=0,f=1;char ch=getchar(); while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } char ch[10]; bool mark[7][1000005]; int ed,q[1000005][7],step[1000005]; int getint(int a[]) { int sum=0; for(int i=1;i<=6;i++) sum=sum*10+a[i]; return sum; } bool jud(int x) { return x==ed; } void bfs() { int t=0,w=1;q[0][0]=1; int tmp=getint(q[0]); mark[1][tmp]=1; if(jud(tmp)){printf("0");return;} while(t!=w) { int a[10],now=q[t][0],s=step[t]; for(int i=1;i<=6;i++) a[i]=q[t][i]; t++;if(t==1000001)t=0; if(now!=1) { swap(a[now],a[1]); tmp=getint(a); if(jud(tmp)){printf("%d",s+1);return;} if(!mark[now][tmp]) { mark[now][tmp]=1;q[w][0]=now;step[w]=s+1; for(int i=1;i<=6;i++)q[w][i]=a[i]; w++;if(w==1000001)w=0; } swap(a[now],a[1]); } if(now!=6) { swap(a[now],a[6]); tmp=getint(a); if(jud(tmp)){printf("%d",s+1);return;} if(!mark[now][tmp]) { mark[now][tmp]=1;q[w][0]=now;step[w]=s+1; for(int i=1;i<=6;i++)q[w][i]=a[i]; w++;if(w==1000001)w=0; } swap(a[now],a[6]); } if(a[now]!=9) { a[now]++; tmp=getint(a); if(jud(tmp)){printf("%d",s+1);return;} if(!mark[now][tmp]) { mark[now][tmp]=1;q[w][0]=now;step[w]=s+1; for(int i=1;i<=6;i++)q[w][i]=a[i]; w++;if(w==1000001)w=0; } a[now]--; } if(a[now]!=0) { a[now]--; tmp=getint(a); if(jud(tmp)){printf("%d",s+1);return;} if(!mark[now][tmp]) { mark[now][tmp]=1;q[w][0]=now;step[w]=s+1; for(int i=1;i<=6;i++)q[w][i]=a[i]; w++;if(w==1000001)w=0; } a[now]++; } if(now!=1) { tmp=getint(a); if(!mark[now-1][tmp]) { mark[now-1][tmp]=1;q[w][0]=now-1;step[w]=s+1; for(int i=1;i<=6;i++)q[w][i]=a[i]; w++;if(w==1000001)w=0; } } if(now!=6) { tmp=getint(a); if(!mark[now+1][tmp]) { mark[now+1][tmp]=1;q[w][0]=now+1;step[w]=s+1; for(int i=1;i<=6;i++)q[w][i]=a[i]; w++;if(w==1000001)w=0; } } } } int main() { //freopen("typer.in","r",stdin); //freopen("typer.out","w",stdout); scanf("%s",ch+1); for(int i=1;i<=6;i++) q[0][i]=ch[i]-'0'; scanf("%d",&ed); bfs(); return 0; } |
黄学长您其实可以把光标左移的操作给删了,不影响正确性的,而且可以在1s内跑完
他也得是虐noip啊。。hzwer大神是神啊。。伸到无法直视。人家天天怒虐福建省队集训,天天AK,人送外号黄金AK大神[崇拜]
OTZ天天虐noip模拟赛的黄学长