hdu1195 Open the Lock
Open the Lock - HDU 1195 - Virtual Judge (csgrandeur.cn)
题目大意:
现在你有个紧急任务,就是打开密码锁。密码由4位数字组成。每位数字编号为1 ~ 9。
每次,你可以对任意数字加或减1。当“9”加1时,数字将变为“1”,当“1”减1时,数字将变为“9”。您也可以与相邻的数字交换。每一个行动只需要迈出一步。
现在你的任务是用最少的步骤打开锁。
注意:最左边的数字不是最右边的数字的邻居。
题解:
由于密码组合一共只有9000种左右,所以直接bfs
也可以作为双向广搜的练习题,可以提高效率
Code:
#include <bits/stdc++.h> //双向广搜
using namespace std;
#define ioss ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
typedef pair<int,int> P;
int S,E;
queue<P> a,b;
int ans;
void init(){
queue<P> e1,e2;
swap(a,e1);
swap(b,e2);
ans=-1;
}
void expand(int num,queue<P> &ss,int dep,int vis[]){
char s[10];
sprintf(s,"%d",num);
for(int i=0;i<4;++i){
if(s[i]<'9'){
s[i]++;
sscanf(s,"%d",&num);
if(!vis[num]){
vis[num]=dep+1;
ss.push(make_pair(num,dep));
}
s[i]--;
}else{
s[i]='1';
sscanf(s,"%d",&num);
if(!vis[num]){
vis[num]=dep+1;
ss.push(make_pair(num,dep));
}
s[i]='9';
}
if(s[i]>'1'){
s[i]--;
sscanf(s,"%d",&num);
if(!vis[num]){
vis[num]=dep+1;
ss.push(make_pair(num,dep));
}
s[i]++;
}else{
s[i]='9';
sscanf(s,"%d",&num);
if(!vis[num]){
vis[num]=dep+1;
ss.push(make_pair(num,dep));
}
s[i]='1';
}
if(i<3){
swap(s[i],s[i+1]);
sscanf(s,"%d",&num);
if(!vis[num]){
vis[num]=dep+1;
ss.push(make_pair(num,dep));
}
swap(s[i],s[i+1]);
}
}
}
void dbfs(){
a.push(make_pair(S,0));
b.push(make_pair(E,0));
int M[10010]={0},N[10010]={0};
N[S]=1;M[E]=1;
while(!a.empty()||!b.empty()){
if(b.empty()||a.size()<=b.size()){ //正向
P tmp=a.front();
int dep=tmp.second;
while(tmp.second==dep){
if(M[tmp.first]){
ans=M[tmp.first]+dep-1;
break;
}
// cout<<tmp.first<<" "<<1<<'\n';
expand(tmp.first,a,dep+1,N);
a.pop();
tmp=a.front();
}
}else{ //反向
P tmp=b.front();
int dep=tmp.second;
while(tmp.second==dep){
if(N[tmp.first]){
ans=N[tmp.first]+dep-1;
break;
}
// cout<<tmp.first<<" "<<2<<'\n';
expand(tmp.first,b,dep+1,M);
b.pop();
tmp=b.front();
}
}
if(ans!=-1)break;
}
cout<<ans<<'\n';
}
int main(){
int T;
cin>>T;
while(T--){
init();
cin>>S>>E;
dbfs();
}
return 0;
}