搜索 问题 D: 神奇密码锁
这道题个人认为隐含着状态转换,所以想到的还是BFS,将其中一位数加一或减一或交换临近两位,进入下一状态,使用一个大小为10000的bool数组判重,由于BFS的特性,得到的一定是最小步数;
普通BFS代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<set>
using namespace std;
const int MaxSize = 1e5;
typedef struct node{
int a[4];
int step;
}Node;
Node Q[MaxSize];
bool visit[10005];
bool search_table(int *a){
int tmp=0;
tmp = a[0]*1000+a[1]*100+a[2]*10+a[3];
if(visit[tmp])return false;
visit[tmp] = true;
return true;
}
int BFS(int *start,int *goal){
int head=0,tail=1,tmp;
memset(visit,0,sizeof(visit));
Node t,s;
memcpy(t.a,start,4*sizeof(int));
t.step = 0;
Q[head] = t;
while(head!=tail){
t = Q[head];
if(!memcmp(t.a,goal,4*sizeof(int))) return t.step;
for(int i=0;i<4;i++){
s = t;
s.a[i]++;
s.step++;
if(s.a[i]>9) s.a[i]=1;
if(search_table(s.a)) {
Q[tail]=s;
tail=(tail+1)%MaxSize;
}
}
for(int i=0;i<4;i++){
s = t;
s.a[i]--;
s.step++;
if(s.a[i]<1) s.a[i]=9;
if(search_table(s.a)) {
Q[tail]=s;
tail=(tail+1)%MaxSize;
}
}
for(int i=0;i<3;i++){
s = t;
tmp = s.a[i],s.a[i] = s.a[i+1],s.a[i+1] = tmp;
s.step++;
if(search_table(s.a)) {
Q[tail]=s;
tail=(tail+1)%MaxSize;
}
}
head=(head+1)%MaxSize;
}
return -1;
}
void Input_data(int *start,int *goal){
char c[5];
scanf("%s",c);
for(int i=0;i<4;i++) start[i] = c[i]-'0';
scanf("%s",c);
for(int i=0;i<4;i++) goal[i] = c[i]-'0';
}
int main(){
int T,start[4],goal[4];
scanf("%d",&T);
while(T--){
Input_data(start,goal);
printf("%d\n",BFS(start,goal));
}
}
双向BFS:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int visit[10005];
const int MaxSize = 1e5;
typedef struct node{
int a[4],step;
}Node;
Node start,goal;
int trans(Node x){
int tmp = 0;
for(int i=0;i<4;i++) tmp = tmp*10+x.a[i];
//printf("%d\n",tmp);
return tmp;
}
Node Q1[MaxSize],Q2[MaxSize];
int BFS(){
memset(visit,0,sizeof(visit));
//queue<Node> Q1,Q2;
Node t,s;
int step1=0,step2=0,ans,cnt;
int head1=0,head2=0,tail1=1,tail2=1;
start.step = 0;
goal.step = 0;
Q1[head1] = start;
Q2[head2] = goal;
visit[trans(start)]=1;
visit[trans(goal)]=2;
while(true){
cnt = (tail1-head1+MaxSize)%MaxSize;
while(cnt--){
t = Q1[head1];
if(!memcmp(t.a,goal.a,sizeof(goal.a))) return t.step;
step1 = t.step + 1;
for(int i=0;i<4;i++){
s = t;
s.a[i]++;
if(s.a[i]>9) s.a[i]=1;
ans = trans(s);
if(visit[ans]==2) return step1+step2;
if(!visit[ans]){
visit[ans] = 1;
s.step = step1;
Q1[tail1]=s;
tail1=(tail1+1)%MaxSize;
}
}
for(int i=0;i<4;i++){
s = t;
s.a[i]--;
if(s.a[i]<1) s.a[i]=9;
ans = trans(s);
if(visit[ans]==2) return step1+step2;
if(!visit[ans]){
visit[ans] = 1;
s.step = step1;
Q1[tail1]=s;
tail1=(tail1+1)%MaxSize;
}
}
for(int i=0;i<3;i++){
s = t;
swap(s.a[i],s.a[i+1]);
ans = trans(s);
if(visit[ans]==2) return step1+step2;
if(!visit[ans]){
visit[ans] = 1;
s.step = step1;
Q1[tail1]=s;
tail1=(tail1+1)%MaxSize;
}
}
head1=(head1+1)%MaxSize;
}
cnt = (tail2-head2+MaxSize)%MaxSize;
while(cnt--){
t = Q2[head2];
if(!memcmp(t.a,start.a,sizeof(start.a))) return t.step;
step2 = t.step + 1;
for(int i=0;i<4;i++){
s = t;
s.a[i]++;
if(s.a[i]>9) s.a[i]=1;
ans = trans(s);
if(visit[ans]==1) return step1+step2;
if(!visit[ans]){
visit[ans] = 2;
s.step = step2;
Q2[tail2]=s;
tail2=(tail2+1)%MaxSize;
}
}
for(int i=0;i<4;i++){
s = t;
s.a[i]--;
if(s.a[i]<1) s.a[i]=9;
ans = trans(s);
if(visit[ans]==1) return step1+step2;
if(!visit[ans]){
visit[ans] = 2;
s.step = step2;
Q2[tail2]=s;
tail2=(tail2+1)%MaxSize;
}
}
for(int i=0;i<3;i++){
s = t;
swap(s.a[i],s.a[i+1]);
ans = trans(s);
if(visit[ans]==1) return step1+step2;
if(!visit[ans]){
visit[ans] = 2;
s.step = step2;
Q2[tail2]=s;
tail2=(tail2+1)%MaxSize;
}
}
head2 = (head2+1)%MaxSize;
}
}
}
void Input_and_solve(){
char ch[5];
scanf("%s",ch);
for(int i=0;i<4;i++) start.a[i] = ch[i]-'0';
scanf("%s",ch);
for(int i=0;i<4;i++) goal.a[i] = ch[i]-'0';
printf("%d\n",BFS());
}
int main(){
int T;
scanf("%d",&T);
while(T--){
Input_and_solve();
}
}
//如有错误,还请留言指出