题目OJ地址:http://cdqz.openjudge.cn/noip/1012/
题目摘要:
-
时间限制: 20000ms
内存限制:128000kB
描述:
阿兰是某机密部门的打字员,她现在接到一个任务:需要在一天之内输入几百个长度同定为6的密码。当然,她希望输入的过程中敲击键盘的总次数越少越好..
不幸的是,出于保密的需要,该部门用于输入密码的键盘是特殊设计的,键盘上没有数字键,而只有以下六个键:Swap0.Swapl,up,down,Left,Right。为了说明这6个键的作用,我们先定义录入区的6个位置的编号,从左至右依次为l,2,3,4,5,6。下面列出每个键的作用:
Swap0:按Swap0,光标位置不变,将光标所在位置的数字与录入区的l号位置的数字(左起第一个数字)交换。如果光标已经处在录入区的l号位置,则按Swap0键之后.录入区的数字不变;
Swapl:按Swapl,光标位置不变,将光标所在位置的数字与录人区的6号位置的数字(左起第六个数字)交换。如果光标已经处在录人区的6号位置,则按Swapl键之后.录人区的数字不变;
Up:按up,光标位置不变,将光标所在位置的数字加1(除非该数字是9)。例如,如果光标所在位置的数字为2,按up之后,该处的数字变为3;如果该处数字为9,则按up之后,数字不变,光标位置也不变;
down:按Down,光标位置不变,将光标所在位置的数宁减1(除非该数字是0)。如果该处数字为0,则按Down之后,数字不变,光标位置也不变;
Left:按Len,光标左移一个位置,如果光标已经在录入区的l号位置(左起笫一个位置)上,则光标不动;
Right:按Right,光标右移一个位置,如果光标已经在录入医的6号位置(左起第六个位置)上,则光标不动。当然,为了使这样的键盘发挥作用,每次录入密码之前,录入区总会随机出现一个长度为6的初始密码.而且光标固定出现在1号位置上。当巧妙地使用上述六个特殊键之后,可以得到目标密码,这时光标允许停在任何一个位置。
现在,阿兰需要你的帮助,编写一个程序,求出录人一个密码需要的最少的击键次数。
-
【输入】
仪一行,含有两个长度为6的数,前者为初始密码,后者为目标密码,两个密码之间用一个空格隔开。
【输出】
仅一行,含有一个正整数,为最少需要的击键次数。
【样例输入】
123456 654321
【样例输出】
11
本题看似很难,其实是一个赤裸裸的BFS。很好处理,时间限制为2s使得不需大量加优化。参考了下钟神的程序和思路,自己终于把它写出来了。钟神的解题报告:
http://www.cnblogs.com/zhonghaoxi/archive/2012/05/25/2518528.html.
常见的优化思路有三种:判重,随机化处理,双向bfs。我只采用了第一种,勉强在1s到2s之间过了。
bfs的方法是:依次进行六种操作,看是否达到目标状态,如果达到就退出,否则压入队列。
记录状态的方法有两种,可以用一个struct来存储当前密码和光标位置,也可以直接用一个7位数,最后一位代表光标位置。判重可以用布尔数组或者集合,推荐使用布尔数组。
为了方便,我们把左起第一位标记为第6位,右起第一位标记为第1位。(因为最高位在最左边,这样方便处理)这样提取六位数s第i位的方法是[s/10^(i-1)] mod 10,然后就可以轻松对这个数进行各种操作了,具体的可以看代码。
Here is the code:


1 #include<iostream> 2 #include<fstream> 3 #include<queue> 4 5 using namespace std; 6 7 ifstream fin("typer.in"); 8 ofstream fout("typer.out"); 9 10 int start,end,ten[11]; 11 bool state[1000000001]; 12 13 struct node 14 { 15 int v,s; 16 17 node() 18 { 19 v=s=0; 20 } 21 22 node(int vv,int ss) 23 { 24 v=vv,s=ss; 25 } 26 }; 27 28 queue<node> q; 29 30 bool go_1(int v,int p,int s) 31 { 32 if(p==6) return false; 33 34 int vnew=v; 35 vnew=vnew-v/ten[6]*ten[6]; 36 vnew=vnew+(v/ten[p])%10*ten[6]; 37 vnew=vnew-(v/ten[p]%10)*ten[p]; 38 vnew=vnew+v/ten[6]*ten[p]; 39 40 if(vnew==end) 41 { 42 cout<<s+1<<endl; 43 return true; 44 } 45 46 if(!state[vnew*10+p]) 47 { 48 state[vnew*10+p]=1; 49 q.push(node(vnew*10+p,s+1)); 50 } 51 return false; 52 } 53 54 bool go_2(int v,int p,int s) 55 { 56 if(p==1) return false; 57 58 int vnew=v; 59 vnew=vnew-v%10; 60 vnew=vnew+(v/ten[p])%10; 61 vnew=vnew-(v/ten[p]%10)*ten[p]; 62 vnew=vnew+(v%10)*ten[p]; 63 64 if(vnew==end) 65 { 66 cout<<s+1<<endl; 67 return true; 68 } 69 70 if(!state[vnew*10+p]) 71 { 72 state[vnew*10+p]=1; 73 q.push(node(vnew*10+p,s+1)); 74 } 75 return false; 76 } 77 78 bool go_3(int v,int p,int s) 79 { 80 if(v/ten[p]%10==9) return false; 81 82 int vnew=v+ten[p]; 83 if(vnew==end) 84 { 85 cout<<s+1<<endl; 86 return true; 87 } 88 89 if(!state[vnew*10+p]) 90 { 91 state[vnew*10+p]=1; 92 q.push(node(vnew*10+p,s+1)); 93 } 94 return false; 95 } 96 97 bool go_4(int v,int p,int s) 98 { 99 if(v/ten[p]%10==0) return false; 100 101 int vnew=v-ten[p]; 102 if(vnew==end) 103 { 104 cout<<s+1<<endl; 105 return true; 106 } 107 108 if(!state[vnew*10+p]) 109 { 110 state[vnew*10+p]=1; 111 q.push(node(vnew*10+p,s+1)); 112 } 113 return false; 114 } 115 116 bool go_5(int v,int p,int s) 117 { 118 if(p==6) return false; 119 120 if(!state[v*10+p+1]) 121 { 122 state[v*10+p+1]=1; 123 q.push(node(v*10+p+1,s+1)); 124 } 125 return false; 126 } 127 128 bool go_6(int v,int p,int s) 129 { 130 if(p==1) return false; 131 132 if(!state[v*10+p-1]) 133 { 134 state[v*10+p-1]=1; 135 q.push(node(v*10+p-1,s+1)); 136 } 137 return false; 138 } 139 140 int main() 141 { 142 cin>>start>>end; 143 if(start==end) 144 { 145 cout<<0<<endl; 146 return 0; 147 } 148 ten[1]=1; 149 for(int i=2;i<=6;i++) 150 ten[i]=ten[i-1]*10; 151 152 q.push(node(start*10+6,0)); 153 state[start*10+6]=1; 154 155 while(!q.empty()) 156 { 157 node t=q.front(); 158 q.pop(); 159 int v=t.v/10,p=t.v%10,s=t.s; 160 161 if(go_1(v,p,s)) break; 162 if(go_2(v,p,s)) break; 163 if(go_3(v,p,s)) break; 164 if(go_4(v,p,s)) break; 165 if(go_5(v,p,s)) break; 166 if(go_6(v,p,s)) break; 167 } 168 169 return 0; 170 }