CDQZ_Training 2012-05-24 聪明的打字员
题目:
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…………………………但需要一定的优化:1、改变每次进行扩展时的操作顺序。2、加判重。3、双向bfs。
- 我只用了第二种优化………………好像比较慢………………不过勉强可以过了………………
1 #include<cstdio>
2 #include<cstdlib>
3 #include<cstring>
4 #include<queue>
5
6 using namespace std;
7
8 int shi[10],s,e;
9
10 bool ma[100000001];
11
12 struct state
13 {
14 int v,step;
15 state()
16 {
17 v=step=0;
18 }
19 state(int a,int b)
20 {
21 v=a;step=b;
22 }
23 };
24
25 queue<state> que;
26
27 bool work1(int v,int p,int s)
28 {
29 if (p==6) return false;
30 int newv=v;
31 newv=newv-v / shi[6] * shi[6];
32 newv=newv-v / shi[p] % 10 * shi[p];
33 newv=newv+v / shi[p] % 10 * shi[6];
34 newv=newv+v / shi[6] * shi[p];
35 if (newv==e)
36 {
37 printf("%d\n",s+1);
38 return true;
39 }
40 if (!ma[newv*10+p])
41 {
42 ma[newv*10+p]=true;
43 que.push(state(newv*10+p,s+1));
44 }
45 return false;
46 }
47
48 bool work2(int v,int p,int s)
49 {
50 if (p==1) return false;
51 int newv=v;
52 newv=newv-v % 10;
53 newv=newv-v / shi[p] % 10 * shi[p];
54 newv=newv+v / shi[p] % 10;
55 newv=newv+v % 10 * shi[p];
56 if (newv==e)
57 {
58 printf("%d\n",s+1);
59 return true;
60 }
61 if (!ma[newv*10+p])
62 {
63 ma[newv*10+p]=true;
64 que.push(state(newv*10+p,s+1));
65 }
66 return false;
67 }
68
69 bool work3(int v,int p,int s)
70 {
71 if (v / shi[p] % 10==9) return false;
72 int newv=v+shi[p];
73 if (newv==e)
74 {
75 printf("%d\n",s+1);
76 return true;
77 }
78 if (!ma[newv*10+p])
79 {
80 ma[newv*10+p]=true;
81 que.push(state(newv*10+p,s+1));
82 }
83 return false;
84 }
85
86 bool work4(int v,int p,int s)
87 {
88 if (v / shi[p] % 10==0) return false;
89 int newv=v-shi[p];
90 if (newv==e)
91 {
92 printf("%d\n",s+1);
93 return true;
94 }
95 if (!ma[newv*10+p])
96 {
97 ma[newv*10+p]=true;
98 que.push(state(newv*10+p,s+1));
99 }
100 return false;
101 }
102
103 bool work5(int v,int p,int s)
104 {
105 if (p==1) return false;
106 int newp=p-1;
107 if (!ma[v*10+newp])
108 {
109 ma[v*10+newp]=true;
110 que.push(state(v*10+newp,s+1));
111 }
112 return false;
113 }
114
115 bool work6(int v,int p,int s)
116 {
117 if (p==6) return false;
118 int newp=p+1;
119 if (!ma[v*10+newp])
120 {
121 ma[v*10+newp]=true;
122 que.push(state(v*10+newp,s+1));
123 }
124 return false;
125 }
126 int main()
127 {
128 scanf("%d%d",&s,&e);
129 if (s==e)
130 {
131 printf("0\n");
132 return 0;
133 }
134 shi[1]=1;
135 for (int a=2;a<=6;a++)
136 shi[a]=shi[a-1]*10;
137 que.push(state(s*10+6,0));
138 ma[s*10+6]=true;
139 while (que.size())
140 {
141 state now=que.front();
142 que.pop();
143 int v=now.v / 10;
144 int p=now.v % 10;
145 if (work1(v,p,now.step)) break;
146 if (work2(v,p,now.step)) break;
147 if (work3(v,p,now.step)) break;
148 if (work4(v,p,now.step)) break;
149 if (work5(v,p,now.step)) break;
150 if (work6(v,p,now.step)) break;
151 }
152
153 return 0;
154 }