poj1184 聰明的打字員

來源:互聯網
上載者:User
L - 聰明的打字員

Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u

Submit Status

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
搜尋的壯態壓縮,其實,左移是沒什麼用的,因為,你大可右移,在右移的時候,就把數值改變了去就可以,因為數值的改變和你游標所在的位置是沒關的,只要,你曾移到過那個位置就可以了,所以,我們可以先把原數的所有的排列求出來,再求出排出後的數列的要移動的步數就可以了,這樣我們先處理012345的所有排列,所要右移和交換的次數,對於其他的任何數,由這個數列進行相對應的變換就可以了!我們開一個visit數組前6個是6個數,最後一個是游標的壯態,我們可以發現,游標的壯態只有10種,這樣用BFS搜尋之後,只有不到273種壯態了,大大的壓縮的,搜尋的難度,時間自然就不成問題了!
#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;}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.