Open the Lock
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 1788 Accepted Submission(s): 747
Problem Description
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.
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.
Input
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.
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.
Output
For each test case, print the minimal steps in one line.
Sample Input
2 1234 2144 1111 9999
Sample Output
2 4
Author
YE, Kai
Source
Recommend
Ignatius.L
这个题,直接使用BFS爆搜是能够过得,31ms
这个题被挂在了我们学校的OJ,数据被一些邪恶的学弟们加强了。。我用了BFS然后果断TLE
题目链接:http://220.166.52.162/oj/showproblem?problem_id=2360
后来得知,需要使用双向BFS。很可惜,自己从未写过双向BFS。于是又跑到网上去看双向BFS的资料。总算看明白了。。(退役的半年里,第一次学习新的算法)
其实思路还是挺简单的,双向就是利用两个BFS拼在一起,一个从起点开始搜索,一个从终点开始搜索
当两个BFS搜索的轨迹有重合的部分的时候,立即停止两个BFS,并根据当前重合点的与两个BFS已得到的信息来计算答案。
贴下代码:(双向BFS也写的很挫,把队列换成数组之后才1000ms卡过去了,当然在HDU上是0ms)
#include<stdio.h>
#include<algorithm>
#include<queue>
#include<string.h>
#include<stdlib.h>
using namespace std;
int A[5],B[5],aim;
int flag[10000];
int ak[10000];
int bk[10000];
struct node
{
int num;
int step;
};
void bfs()
{
memset(flag,0,sizeof(flag));
node k1,k2,k3,k4;
int tmp[5],i,now[5],mt;
node q1[10000];
node q2[10000];
int h1=0,t1=0,h2=0,t2=0;
k1.num=A[1]*1000+A[2]*100+A[3]*10+A[4];
flag[k1.num]=1;
ak[k1.num]=0;
k1.step=0;
k3.num=B[1]*1000+B[2]*100+B[3]*10+B[4];
k3.step=0;
bk[k3.num]=0;
flag[k3.num]=2;
q1[t1++]=k1;
q2[t2++]=k3;
while(h1!=t1||h2!=t2)
{
int len1=t1-h1;
while(len1--)
{
k2=q1[h1++];
tmp[1]=k2.num/1000;
tmp[2]=(k2.num%1000)/100;
tmp[3]=(k2.num%100)/10;
tmp[4]=k2.num%10;
for(i=1;i<=4;i++)
{
now[1]=tmp[1];
now[2]=tmp[2];
now[3]=tmp[3];
now[4]=tmp[4];
now[i]=tmp[i]+1;
if(now[i]==10)
now[i]=1;
mt=now[1]*1000+now[2]*100+now[3]*10+now[4];
if(flag[mt]==2)
{
printf("%d\n",k2.step+bk[mt]+1);
return;
}
if(!flag[mt])
{
flag[mt]=1;
k1.num=mt;
k1.step=k2.step+1;
ak[mt]=k1.step;
q1[t1++]=k1;
}
}
for(i=1;i<=4;i++)
{
now[1]=tmp[1];
now[2]=tmp[2];
now[3]=tmp[3];
now[4]=tmp[4];
now[i]=tmp[i]-1;
if(now[i]==0)
now[i]=9;
mt=now[1]*1000+now[2]*100+now[3]*10+now[4];
if(flag[mt]==2)
{
printf("%d\n",k2.step+bk[mt]+1);
return;
}
if(!flag[mt])
{
flag[mt]=1;
k1.num=mt;
k1.step=k2.step+1;
ak[mt]=k1.step;
q1[t1++]=k1;
}
}
now[1]=tmp[2];
now[2]=tmp[1];
now[3]=tmp[3];
now[4]=tmp[4];
mt=now[1]*1000+now[2]*100+now[3]*10+now[4];
if(flag[mt]==2)
{
printf("%d\n",k2.step+bk[mt]+1);
return;
}
if(!flag[mt])
{
flag[mt]=1;
k1.num=mt;
k1.step=k2.step+1;
ak[mt]=k1.step;
q1[t1++]=k1;
}
now[1]=tmp[1];
now[2]=tmp[3];
now[3]=tmp[2];
now[4]=tmp[4];
mt=now[1]*1000+now[2]*100+now[3]*10+now[4];
if(flag[mt]==2)
{
printf("%d\n",k2.step+bk[mt]+1);
return;
}
if(!flag[mt])
{
flag[mt]=1;
k1.num=mt;
k1.step=k2.step+1;
ak[mt]=k1.step;
q1[t1++]=k1;
}
now[1]=tmp[1];
now[2]=tmp[2];
now[3]=tmp[4];
now[4]=tmp[3];
mt=now[1]*1000+now[2]*100+now[3]*10+now[4];
if(flag[mt]==2)
{
printf("%d\n",k2.step+bk[mt]+1);
return;
}
if(!flag[mt])
{
flag[mt]=1;
k1.num=mt;
k1.step=k2.step+1;
ak[mt]=k1.step;
q1[t1++]=k1;
}
// printf("%d %d %d 1\n",k2.num,k2.step,ak[k2.num]);
// system("pause");
}
int len2=t2-h2;
while(len2--)
{
k4=q2[h2++];
tmp[1]=k4.num/1000;
tmp[2]=(k4.num%1000)/100;
tmp[3]=(k4.num%100)/10;
tmp[4]=k4.num%10;
for(i=1;i<=4;i++)
{
now[1]=tmp[1];
now[2]=tmp[2];
now[3]=tmp[3];
now[4]=tmp[4];
now[i]=tmp[i]+1;
if(now[i]==10)
now[i]=1;
mt=now[1]*1000+now[2]*100+now[3]*10+now[4];
if(flag[mt]==1)
{
printf("%d\n",ak[mt]+k4.step+1);
return;
}
if(!flag[mt])
{
flag[mt]=2;
k3.num=mt;
k3.step=k4.step+1;
bk[mt]=k3.step;
q2[t2++]=k3;
}
}
for(i=1;i<=4;i++)
{
now[1]=tmp[1];
now[2]=tmp[2];
now[3]=tmp[3];
now[4]=tmp[4];
now[i]=tmp[i]-1;
if(now[i]==0)
now[i]=9;
mt=now[1]*1000+now[2]*100+now[3]*10+now[4];
// printf("%d %d\n",mt,ak[mt]);
if(flag[mt]==1)
{
printf("%d\n",ak[mt]+k4.step+1);
return;
}
if(!flag[mt])
{
flag[mt]=2;
k3.num=mt;
k3.step=k4.step+1;
bk[mt]=k3.step;
q2[t2++]=k3;
}
}
now[1]=tmp[2];
now[2]=tmp[1];
now[3]=tmp[3];
now[4]=tmp[4];
mt=now[1]*1000+now[2]*100+now[3]*10+now[4];
if(flag[mt]==1)
{
printf("%d\n",ak[mt]+k4.step+1);
return;
}
if(!flag[mt])
{
flag[mt]=2;
k3.num=mt;
k3.step=k4.step+1;
bk[mt]=k3.step;
q2[t2++]=k3;
}
now[1]=tmp[1];
now[2]=tmp[3];
now[3]=tmp[2];
now[4]=tmp[4];
mt=now[1]*1000+now[2]*100+now[3]*10+now[4];
if(flag[mt]==1)
{
printf("%d\n",ak[mt]+k4.step+1);
return;
}
if(!flag[mt])
{
flag[mt]=2;
k3.num=mt;
k3.step=k4.step+1;
bk[mt]=k3.step;
q2[t2++]=k3;
}
now[1]=tmp[1];
now[2]=tmp[2];
now[3]=tmp[4];
now[4]=tmp[3];
mt=now[1]*1000+now[2]*100+now[3]*10+now[4];
if(flag[mt]==1)
{
printf("%d\n",ak[mt]+k4.step+1);
return;
}
if(!flag[mt])
{
flag[mt]=2;
k3.num=mt;
k3.step=k4.step+1;
bk[mt]=k3.step;
q2[t2++]=k3;
}
// printf("%d %d %d 2\n",k4.num,k4.step,bk[k4.num]);
// system("pause");
}
}
}
int main()
{
int t,tk,ts;
scanf("%d",&t);
while(t--)
{
scanf("%d",&tk);
scanf("%d",&ts);
if(tk==ts)
{
printf("0\n");
continue;
}
A[1]=tk/1000;
A[2]=(tk%1000)/100;
A[3]=(tk%100)/10;
A[4]=tk%10;
B[1]=ts/1000;
B[2]=(ts%1000)/100;
B[3]=(ts%100)/10;
B[4]=ts%10;
aim=B[1]*1000+B[2]*100+B[3]*10+B[4];
bfs();
}
return 0;
}
附录:
为了便于才学算法的新人,贴出本人TLE的单向BFS代码(HDU上31ms)
代码:
#include<stdio.h>
#include<algorithm>
#include<queue>
#include<string.h>
using namespace std;
int A[5],B[5],aim;
bool flag[10000];
struct node
{
int num;
int step;
};
void bfs()
{
memset(flag,0,sizeof(flag));
node k1,k2;
int tmp[5],i,now[5],mt;
queue<node>q;
k1.num=A[1]*1000+A[2]*100+A[3]*10+A[4];
flag[k1.num]=true;
k1.step=0;
q.push(k1);
while(!q.empty())
{
k2=q.front();
q.pop();
if(k2.num==aim)
{
printf("%d\n",k2.step);
break;
}
tmp[1]=k2.num/1000;
tmp[2]=(k2.num%1000)/100;
tmp[3]=(k2.num%100)/10;
tmp[4]=k2.num%10;
for(i=1;i<=4;i++)
{
now[1]=tmp[1];
now[2]=tmp[2];
now[3]=tmp[3];
now[4]=tmp[4];
now[i]=tmp[i]+1;
if(now[i]==10)
now[i]=1;
mt=now[1]*1000+now[2]*100+now[3]*10+now[4];
if(!flag[mt])
{
flag[mt]=true;
k1.num=mt;
k1.step=k2.step+1;
q.push(k1);
}
}
for(i=1;i<=4;i++)
{
now[1]=tmp[1];
now[2]=tmp[2];
now[3]=tmp[3];
now[4]=tmp[4];
now[i]=tmp[i]-1;
if(now[i]==0)
now[i]=9;
mt=now[1]*1000+now[2]*100+now[3]*10+now[4];
if(!flag[mt])
{
flag[mt]=true;
k1.num=mt;
k1.step=k2.step+1;
q.push(k1);
}
}
now[1]=tmp[2];
now[2]=tmp[1];
now[3]=tmp[3];
now[4]=tmp[4];
mt=now[1]*1000+now[2]*100+now[3]*10+now[4];
if(!flag[mt])
{
flag[mt]=true;
k1.num=mt;
k1.step=k2.step+1;
q.push(k1);
}
now[1]=tmp[1];
now[2]=tmp[3];
now[3]=tmp[2];
now[4]=tmp[4];
mt=now[1]*1000+now[2]*100+now[3]*10+now[4];
if(!flag[mt])
{
flag[mt]=true;
k1.num=mt;
k1.step=k2.step+1;
q.push(k1);
}
now[1]=tmp[1];
now[2]=tmp[2];
now[3]=tmp[4];
now[4]=tmp[3];
mt=now[1]*1000+now[2]*100+now[3]*10+now[4];
if(!flag[mt])
{
flag[mt]=true;
k1.num=mt;
k1.step=k2.step+1;
q.push(k1);
}
}
}
int main()
{
int t,tk,ts;
scanf("%d",&t);
while(t--)
{
scanf("%d",&tk);
scanf("%d",&ts);
A[1]=tk/1000;
A[2]=(tk%1000)/100;
A[3]=(tk%100)/10;
A[4]=tk%10;
B[1]=ts/1000;
B[2]=(ts%1000)/100;
B[3]=(ts%100)/10;
B[4]=ts%10;
aim=B[1]*1000+B[2]*100+B[3]*10+B[4];
bfs();
}
return 0;
}