poj1184 聪明的打字员

来源:互联网 发布:xclient mac 编辑:程序博客网 时间:2024/05/01 03:51
聪明的打字员
Time Limit: 1000MS Memory Limit: 65536KTotal Submissions: 5839 Accepted: 1190

Description

阿兰是某机密部门的打字员,她现在接到一个任务:需要在一天之内输入几百个长度固定为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号位置上。当巧妙地使用上述六个特殊键之后,可以得到目标密码,这时光标允许停在任何一个位置。 
现在,阿兰需要你的帮助,编写一个程序,求出录入一个密码需要的最少的击键次数。 

Input

仅一行,含有两个长度为6的数,前者为初始密码,后者为目标密码,两个密码之间用一个空格隔开。

Output

仅一行,含有一个正整数,为最少需要的击键次数。

Sample Input

123456 654321

Sample Output

11

Source

Noi 01
这个还是队友写的,不过感觉好长,还没搞懂,以后再看吧
Memory: 2540 KB Time: 32 MS Language: G++ Result: Accepted
#include<string.h>#include<stdio.h>#include<math.h>#include<iostream>using namespace std;int visit[6][6][6][6][6][6][10],flag[6],maxx,aim[6],start[6];struct tree{int pos,state,num[6],step;}queue[50000];int sign[10][6]=//总共10号位{1,0,0,0,0,0,//01,1,0,0,0,0,//11,1,1,0,0,0,//21,1,1,1,0,0,//31,1,1,1,1,0,//41,1,1,1,1,1,//51,0,0,0,0,1,//61,1,0,0,0,1,//71,1,1,0,0,1,//81,1,1,1,0,1//9};int findstate(int ss[]){    int i,sum;    sum=0;    for(i=0;i<6;i++)    {if(ss[i]!=0)        sum=sum*10+1;else sum=sum*10;    }i=sum;    if(i==100000)    return 0;    else if(i==110000)    return 1;    else if(i==111000)    return 2;    else if(i==111100)    return 3;    else if(i==111110)    return 4;    else if(i==111111)    return 5;    else if(i==100001)    return 6;    else if(i==110001)    return 7;    else if(i==111001)    return 8;    else if(i==111101)    return 9;}int changestate(int i,int state)//根据几个状态的关系,来改变{    if(i==0)    {        if(state<=4||(state>=6&&state<=8))        return state+1;        else if((state==5)||(state==9))        return 5;    }    else if(i==1)    {        if(state<=3)        return state+6;        else if(state>=5)        return state;        else if(state==4)//4号位上交换,就成了5号位        return 5;    }    else if(i==2)//和第一号位交换不改变state的状态    return state;}void  changnum(int i,int t,int w){    int * p=queue[t].num,j;    for(j=0;j<6;j++)    {        queue[w].num[j]=*(p+j);//先把num的值改变    }    if(i==0)//只有交换才改变num 的值,只有交换不改变num的值     {       return ;    }    else if(i==1)    {     queue[w].num[queue[w].pos]=*(p+5);     queue[w].num[5]=*(p+queue[w].pos);//五号位的和当前位的地方交换     return;    }    else if(i==2)    {        queue[w].num[queue[w].pos]=*(p);        queue[w].num[0]=*(p+queue[w].pos);//0号位的和当前位的地方交换        return ;    }}bool visitcan ( int w){    int * p=queue[w].num ;    return visit[*p][*(p+1)][*(p+2)][*(p+3)][*(p+4)][*(p+5)][queue[w].state];}int changevisit(int w){    int * p=queue[w].num;    visit[*p][*(p+1)][*(p+2)][*(p+3)][*(p+4)][*(p+5)][queue[w].state]=1;return 1;}void bfs(){    memset(visit,0,sizeof(visit));    int t,w,i,state,pos,step;    t=w=1;    queue[1].pos=0;    for(i=0;i<6;i++)        queue[1].num[i]=i;    queue[1].state=0;    queue[1].step=0;    visit[0][1][2][3][4][5][0]=1;    while(t<=w)    {        state=queue[t].state;        pos=queue[t].pos;        step=queue[t].step;       for(i=0;i<=2;i++)//三种操作,右移交6,交1号位       {                w++;                if(i==0)//右移                {if(queue[t].pos==5)//到过右边不能移动{w--;continue;}                queue[w].pos=queue[t].pos+1;//光标的位置要加一                queue[w].state=changestate(i,state);                queue[w].step=step+1;                changnum(i,t,w);//右移数值不变                if(visitcan(w))                w--;                else                changevisit(w);                }                else if(i==1)                {if(queue[t].pos==5)//在5号不用交换{w--;continue;}                queue[w].pos=queue[t].pos;//交换5号位的光标位置不变                queue[w].state=changestate(i,state);                queue[w].step=step+1;                changnum(i,t,w);                if(visitcan(w))                w--;                else                changevisit(w);                }                else if(i==2)                {if(queue[t].pos==0)//在0号不用交换{w--;continue;}                queue[w].pos=queue[t].pos;//交换0号位的光标位置不变                queue[w].state=changestate(i,state);                queue[w].step=step+1;                changnum(i,t,w);                if(visitcan(w))                w--;                else                changevisit(w);                }        }        t++;    }    maxx=w;    return ;}void init(int s,int e)//把s和e 分解开来{    int num=5;   while(s)   {       start[num]=s%10;       s=s/10;       num--;   }   num=5;   while(e)   {       aim[num]=e%10;       num--;       e=e/10;   }   return ;}bool statecan(int ss[],int i){int sss[6],j;for(j=0;j<6;j++){sss[j]=sign[i][j];if((ss[j]==1)&&(sss[j]!=1))return false; }return true;}int main (){    int s,e,i,k,j,minx,ans,*p,state,temp[6];    bfs();//搜索各种排列的要的步数,不用考虑输入和输出的值        while(scanf("%d%d",&s,&e)!=EOF)    { minx=0x4f4f4f4f;        init(s,e);//将初始位置进行变换for(j=0;j<6;j++)temp[j]=start[j];        for(i=1;i<=maxx;i++)//枚举出所有的数列        {            ans=0;p=queue[i].num;            for(j=0;j<6;j++)//每一轮flag要更新            {                flag[j]=0;                           }            state=0;                      for(j=0;j<6;j++)            {                k=fabs(temp[*(p+j)]-aim[j]);                ans+=k;if(k!=0)                {                    flag[j]=1;                }}            state=findstate(flag);            if(statecan(flag,queue[i].state)){            ans+=queue[i].step;            if(ans<minx){            minx=ans;}}        }                    printf("%d\n",minx);          }    return 0;}