(2189): 【基础算法】解锁

来源:互联网 发布:电脑绘图板软件 编辑:程序博客网 时间:2024/06/14 12:36
时间限制: 1 Sec  内存限制: 128 MB

题目描述

Now an emergent task for you is to open a password lock. The password is consisted of four digits. Each digit is numbered from 1 to 9. 
Each time, you can add or minus 1 to any digit. When add 1 to '9', the digit will change to be '1' and when minus 1 to '1', the digit will change to be '9'. You can also exchange the digit with its neighbor. Each action will take one step.
Now your task is to use minimal steps to open the lock.
Note: The leftmost digit is not the neighbor of the rightmost digit.
The input file begins with an integer T, indicating the number of test cases.

输入

Each test case begins with a four digit N, indicating the initial state of the password lock. Then followed a line with anotther four dight M, indicating the password which can open the lock. There is one blank line after each test case.

输出

For each test case, print the minimal steps in one line.

样例输入

 (如果复制到控制台无换行,可以先粘贴到文本编辑器,再复制)

21234214411119999

样例输出

24



虽然英语140+的我可以直接看懂题目,但我还是翻出来好了_(:з」∠)_

翻译:

你需要开一个密码锁,它有4位数,分别从1-9。每一步中,你可以对某一位数+1(若原数为9,则操作后为1),或-1(若原数为1,则操作后为9),或将相邻两位数交换(第一位数和第四位数不相邻)。

题目有多组数据,第一行为数据个数,接下来每组数据中第一行为开始状态,第二行为结束状态。相邻两组数据间有空行。
对每组数据,输出最少的步数。

反正都是bfs,标记却有两种方式。
第一种,直接用一个四位数表示,那叫一个不直观,特烧脑,想当初我还就是这么做的,调了半天...结果因为在某处忽略了一个括号RE了好久...
当然最后还是AC了。
#include<cstdio>#include<queue>#include<cstring>using namespace std;int n,bg,ed,vsd[10005];struct dgt{    int num,ts;}p,r;queue<dgt>q;int main(){    int i,j,k,lft,rht;    scanf("%d",&n);    for(i=1;i<=n;i++)    {        scanf("%d%d",&bg,&ed);        p.ts=0;p.num=bg;        memset(vsd,0,sizeof(vsd));        while(!q.empty()) q.pop();        vsd[bg]=1;        q.push(p);        while(!q.empty())        {            p=q.front();            q.pop();            if(p.num==ed)            {                printf("%d\n",p.ts);                break;            }            for(j=1;j<=1000;j*=10)            {                lft=p.num/j/10;                rht=p.num%j;                k=(p.num/j)%10+1;                if(k==10) k=1;                if(!vsd[lft*10*j+k*j+rht])                {                    vsd[lft*10*j+k*j+rht]=1;                    r.ts=p.ts+1;r.num=lft*10*j+k*j+rht;                    q.push(r);                }                k=(p.num/j)%10-1;                if(!k) k=9;                if(!vsd[lft*10*j+k*j+rht])                {                    vsd[lft*10*j+k*j+rht]=1;                    r.ts=p.ts+1;r.num=lft*10*j+k*j+rht;                    q.push(r);                }            }            r.num=1000*((p.num/100)%10)+100*(p.num/1000)+p.num%100;            if(!vsd[r.num])            {                vsd[r.num]=1;                q.push(r);            }            r.num=1000*(p.num/1000)+100*((p.num/10)%10)+10*((p.num/100)%10)+p.num%10;            if(!vsd[r.num])            {                vsd[r.num]=1;                q.push(r);            }            r.num=100*(p.num/100)+10*(p.num%10)+(p.num/10)%10;            if(!vsd[r.num])            {                vsd[r.num]=1;                q.push(r);            }        }    }}

至于其中的原理,还请各位自己研究...
第二种,把每位数分别存起来,相对第一种来说,直观了很多啊...(至于用字符串存还是先输入整数再分别取你们自己看着办)
这里随便找了一个大犇&萌妹子的代码...0ms还是很强势。至少比起我4ms的代码......
#include<iostream>#include<algorithm>#include<cstdio>#include<cstdlib>#include<cstring>#include<ctime>#include<cmath>#include<queue>using namespace std;struct node{    char a,b,c,d;    int step;    node(){}    node(int q,int w,int e,int r,int t){        a=q,b=w,c=e,d=r,step=t;    }}tmp;queue <node> q;int T;char s[6],end[6];bool vis[10][10][10][10];int add(int x){    if(x==9)    return 1;    else    return x+1;}int cut(int x){    if(x==1)    return 9;    else    return x-1;}int bfs(){    while(!q.empty())           q.pop();    q.push(node(s[1]-48,s[2]-48,s[3]-48,s[4]-48,0));    while(!q.empty()){        tmp=q.front(),q.pop();        int a=tmp.a,b=tmp.b,c=tmp.c,d=tmp.d;        vis[a][b][c][d]=1;        if(a==end[1]-48&&b==end[2]-48&&c==end[3]-48&&d==end[4]-48)            return tmp.step;        if(!vis[add(a)][b][c][d])            q.push(node(add(a),b,c,d,tmp.step+1)),vis[add(a)][b][c][d]=1;        if(!vis[a][add(b)][c][d])            q.push(node(a,add(b),c,d,tmp.step+1)),vis[a][add(b)][c][d]=1;        if(!vis[a][b][add(c)][d])            q.push(node(a,b,add(c),d,tmp.step+1)),vis[a][b][add(c)][d]=1;        if(!vis[a][b][c][add(d)])            q.push(node(a,b,c,add(d),tmp.step+1)),vis[a][b][c][add(d)]=1;                     if(!vis[cut(a)][b][c][d])            q.push(node(cut(a),b,c,d,tmp.step+1)),vis[cut(a)][b][c][d]=1;        if(!vis[a][cut(b)][c][d])            q.push(node(a,cut(b),c,d,tmp.step+1)),vis[a][cut(b)][c][d]=1;        if(!vis[a][b][cut(c)][d])            q.push(node(a,b,cut(c),d,tmp.step+1)),vis[a][b][cut(c)][d]=1;        if(!vis[a][b][c][cut(d)])            q.push(node(a,b,c,cut(d),tmp.step+1)),vis[a][b][c][cut(d)]=1;                 if(!vis[b][a][c][d])            q.push(node(b,a,c,d,tmp.step+1)),vis[b][a][c][d]=1;        if(!vis[a][c][b][d])            q.push(node(a,c,b,d,tmp.step+1)),vis[a][c][b][d]=1;        if(!vis[a][b][d][c])            q.push(node(a,b,d,c,tmp.step+1)),vis[a][b][d][c]=1;    }    return -1;}int main(){    scanf("%d",&T);    while(T--){        memset(vis,0,sizeof(vis));        scanf("%s%s",s+1,end+1);        printf("%d\n",bfs());    }}


至于用数字来做的方法就直接略了吧 = =

这个寒假作业真的好多
0 0