NC16883. [NOI2001]聪明的打字员
描述
阿兰是某机密部门的打字员,她现在接到一个任务:需要在一天之内输入几百个长度固定为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的数,前者为初始密码,后者为目标密码,两个密码之间用一个空格隔开。
输出描述
仅一行,含有一个正整数,为最少需要的击键次数。
示例1
输入:
123456 654321
输出:
11
说明:
C++14(g++5.4) 解法, 执行用时: 15ms, 内存消耗: 6240K, 提交时间: 2019-01-07 16:55:43
#include <cstdio> #include <queue> #include <cstring> using namespace std; #define N 1000005 #define M 7 #define UP 1 #define DOWN -1 char a[M], b[M]; int factor[M], num[6]; bool vis[N][6]; struct Node{ int val, idx, step; Node(int v, int i, int s): val(v), idx(i), step(s) {} }; int get_hash(char s[M]){ int res = 0; for(int i = 0; i < 6; ++i) res = s[i] - '0' + res * 10; return res; } inline int swap(int num, int idx1, int idx2){ int v1 = (num / factor[idx1]) % 10; int v2 = (num / factor[idx2]) % 10; num += (v2 - v1) * factor[idx1]; num += (v1 - v2) * factor[idx2]; return num; } inline int up_down(int num, int idx, int ops){ return num + ops * factor[idx]; } int bfs(int orig, int dest){ memset(vis, false, sizeof(vis)); queue<Node> qu; qu.push(Node(orig, 0, 0)); vis[orig][0] = true; while(!qu.empty()){ Node cur = qu.front(); qu.pop(); int sta = cur.val, idx = cur.idx, step = cur.step; if(sta == dest) return step; ++step; if(idx != 0){ //swap0 int next = swap(sta, 0, idx); if(!vis[next][idx]) qu.push(Node(next, idx, step)), vis[next][idx] = true; } if(idx != 5){ //swap1 int next = swap(sta, 5, idx); if(!vis[next][idx]) qu.push(Node(next, idx, step)), vis[next][idx] = true; } int val = (sta / factor[idx]) % 10; if(val != 9 && val != num[idx]){ //up int next = up_down(sta, idx, UP); if(!vis[next][idx]) qu.push(Node(next, idx, step)), vis[next][idx] = true; } if(val != 0 && val != num[idx]){ //down int next = up_down(sta, idx, DOWN); if(!vis[next][idx]) qu.push(Node(next, idx, step)), vis[next][idx] = true; } if(idx != 0 && (idx == 5 || val == num[idx])){ //left if(!vis[sta][idx - 1]) qu.push(Node(sta, idx - 1, step)), vis[sta][idx - 1] = true; } if(idx != 5 && (idx == 0 || val == num[idx])){ //right if(!vis[sta][idx + 1]) qu.push(Node(sta, idx + 1, step)), vis[sta][idx + 1] = true; } } return -1; } int main(){ factor[5] = 1; for(int i = 4; i >= 0; --i) factor[i] = 10 * factor[i + 1]; scanf("%s %s", a, b); for(int i = 0; i < 6; ++i) num[i] = b[i] - '0'; int orig = get_hash(a), dest = get_hash(b); printf("%d\n", bfs(orig, dest)); return 0; }
C++(g++ 7.5.0) 解法, 执行用时: 905ms, 内存消耗: 27860K, 提交时间: 2022-09-12 13:23:02
#include<bits/stdc++.h> #define endl "\n" #define ll long long #define int long long #define INF 0x7fffffff using namespace std; inline int rd(void) { int 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; } inline void print(int x) { if (x < 0) { putchar('-'); x = -x; } if (x > 9) print(x / 10); putchar(x % 10 + '0'); } int ksm(int a, int b) { int ans = 1, base = a; while (b) { if (b & 1) ans = ans * base; base = base * base; b >>= 1; } return ans; } const int maxn = 999999 * 10 + 20; int T, n, m; bool vis[maxn]; int a[8]; struct ss { int x, val, pos; }; void solve() { cin >> n >> m; a[6] = 1; for (int i = 5; i >=1; i--) a[i] = a[i + 1] * 10; ss temp{ n * 10 + 1,0,1 }; queue<ss>q; q.push(temp); while (!q.empty()) { int x = q.front().x, v = q.front().val, pos = q.front().pos; q.pop(); x /= 10; if (x == m) { cout << v << endl; return; } int k; if (pos != 1) { k = x * 10 + pos - 1; if (!vis[k]) { vis[k] = 1; ss tmp{ k,v + 1,pos - 1 }; q.push(tmp); } } if (pos != 6) { k = x * 10 + pos + 1; if (!vis[k]) { vis[k] = 1; ss tmp{ k,v + 1,pos + 1 }; q.push(tmp); } } int tt = (x / a[pos]) % 10; if (tt != 0) { k = x - a[pos]; k = k * 10 + pos; if (!vis[k]) { vis[k] = 1; ss tmp{ k,v + 1,pos }; q.push(tmp); } } if (tt != 9) { k = x + a[pos]; k = k * 10 + pos; if (!vis[k]) { vis[k] = 1; ss tmp{ k,v + 1,pos }; q.push(tmp); } } if (pos != 1) { int v1 = (x / a[1]) % 10, vp = (x / a[pos]) % 10; k = x - v1 * a[1] + vp * a[1] - vp * a[pos] + v1 * a[pos] ; k = k * 10 + pos; if (!vis[k]) { vis[k] = 1; ss tmp{ k,v + 1,pos }; q.push(tmp); } } if (pos != 6) { int v6 = (x / a[6]) % 10, vp = (x / a[pos]) % 10; k = x - v6 * a[6] + vp * a[6] - vp * a[pos] + v6 * a[pos] ; k = k * 10 + pos; if (!vis[k]) { vis[k] = 1; ss tmp{ k,v + 1,pos }; q.push(tmp); } } } } signed main() { T = 1; //cin >> T; while (T--) { solve(); } return 0; }
C++ 解法, 执行用时: 5ms, 内存消耗: 2444K, 提交时间: 2021-12-11 14:19:19
#include <cstdio> #include <cstring> #include <iostream> using namespace std; int a,b,sa[8],sb[8],q[100005][8],head=0,tail=0; bool h[10][10][10][10][10][10][7]; inline void mk(int*s){h[s[1]][s[2]][s[3]][s[4]][s[5]][s[6]][s[7]]=true;} inline bool vis(int*s){return h[s[1]][s[2]][s[3]][s[4]][s[5]][s[6]][s[7]];} inline bool enq(int*s) { if(!vis(s)) { mk(s); s[0]++; memcpy(q[tail++],s,sizeof(q[tail])); s[0]--; } int i; for(i=1;i<=6;i++)if(q[head-1][i]!=sb[i])break; if(i==7) { printf("%d\n",q[head-1][0]); return true; } return false; } int main() { scanf("%d%d",&a,&b); if(a==b) { printf("0\n"); return 0; } for(int i=6;i>=1;i--){sa[i]=a%10;a/=10;} for(int i=6;i>=1;i--){sb[i]=b%10;b/=10;} sa[0]=0;sa[7]=1; memcpy(q[tail++],sa,sizeof(sa)); mk(sa); while(head<tail) { int state[8]; memcpy(state,q[head++],sizeof(q[head])); if(state[7]!=1) { swap(state[state[7]],state[1]); if(enq(state))return 0; swap(state[state[7]],state[1]); } if(state[7]!=6) { swap(state[state[7]],state[6]); if(enq(state))return 0; swap(state[state[7]],state[6]); } if(state[state[7]]!=9) { state[state[7]]++; if(enq(state))return 0; state[state[7]]--; } if(state[state[7]]!=0) { state[state[7]]--; if(enq(state))return 0; state[state[7]]++; } //memcpy(state,q[head],sizeof(q[head])); if(state[7]==1 || state[7]==6 || state[state[7]]==sb[state[7]]) { if(state[7]!=1) { state[7]--; if(enq(state))return 0; state[7]++; } if(state[7]!=6) { state[7]++; if(enq(state))return 0; state[7]--; } } } return 0; }