题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1195
推荐一个个人感觉讲解得比较好的DBFS的博客
http://blog.sina.com.cn/s/blog_8627bf080100ticx.html
所谓双向广搜,就是初始结点向目标结点和目标结点向初始结点同时扩展,直至在两个扩展方向上出现同一个结点,搜索结束。它适用的问题是,扩展结点较多,而目标结点又处在深沉,如果采用单纯的广搜解题,搜索量巨大,搜索速度慢是可想而知的,同时往往也会出现内存空间不够用的情况,这时双向广搜的作用就体现出来了。双向广搜对单纯的广搜进行了改良或改造,加入了一定的“智能因数”,使搜索能尽快接近目标结点,减少了在空间和时间上的复杂度。
思路:
这道题不是很难,主要是用来练习一下搜索。
用基础的BFS就可以过,时间46ms,不明白为什么discuss里会有超时的现象。
每次搜索遍历11个方向,每个数位加减一或者交换相邻数位。
用DBFS,时间0ms,用两个队列,从起始两个方向开始搜索,开标记数组,若第一个队列访问过标记为1,第二个队列访问过标记为2。
若都放访问过,说明在两个扩展方向上出现同一个节点,搜索结束。
BFS:
#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <algorithm>
#include <iostream>
#include <iterator>
#include <sstream>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <set>
//#define ONLINE_JUDGE
#define eps 1e-6
#define INF 0x7fffffff //INT_MAX
#define inf 0x3f3f3f3f //int??????????????????
#define FOR(i,a) for((i)=0;i<(a);(i)++) //[i,a);
#define MEM(a) (memset((a),0,sizeof(a)))
#define sfs(a) scanf("%s",a)
#define sf(a) scanf("%d",&a)
#define sfI(a) scanf("%I64d",&a)
#define pf(a) printf("%d\n",a)
#define pfI(a) printf("%I64d\n",a)
#define pfs(a) printf("%s\n",a)
#define sfd(a,b) scanf("%d%d",&a,&b)
#define sft(a,b,c)scanf("%d%d%d",&a,&b,&c)
#define for1(i,a,b) for(int i=(a);i<b;i++)
#define for2(i,a,b) for(int i=(a);i<=b;i++)
#define for3(i,a,b)for(int i=(b);i>=a;i--)
#define MEM1(a) memset(a,0,sizeof(a))
#define MEM2(a) memset(a,-1,sizeof(a))
#define MEM3(a) memset(a,0x3f,sizeof(a))
#define MEMS(a) memset(a,'\0',sizeof(a))
#define LL __int64
const double PI = acos(-1.0);
template<class T> T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }
template<class T> T lcm(T a, T b) { return a / gcd(a, b) * b; }
template<class T> inline T Min(T a, T b) { return a < b ? a : b; }
template<class T> inline T Max(T a, T b) { return a > b ? a : b; }
using namespace std;
template<class T>
T Mint(T a, T b, T c) {
if (a>b) {
if (c>b)
return b;
return c;
}
if (c>a)
return a;
return c;
}
template<class T>
T Maxt(T a, T b, T c) {
if (a>b) {
if (c>a)
return c;
return a;
}
else if (c > b)
return c;
return b;
}
const int maxn=10005;
int T,n,m,k;
int init[4],ans[4],dis[2]={-1,1};
int f[9]={9,1,2,3,4,5,6,7,8};//数表
bool vis[maxn];//标记数组
struct node{
int a[4];
int step;
};
int fun(node p){//计算该数大小
int ans=0;
for1(i,0,4)
ans=ans*10+p.a[i];
return ans;
}
int bfs(){
MEM1(vis);
queue<node>q;
node s,e,t;
for1(i,0,4)
s.a[i]=init[i];
s.step=0;
int sum=fun(s);
vis[sum]=1;
q.push(s);
while(!q.empty()){
s=q.front();
q.pop();
if(fun(s)==k) return s.step;
for1(i,0,4){// // 每位数 加1或减1(若相应位置与答案不同)
if(s.a[i]!=ans[i]){
for1(j,0,2){
t=s;
t.a[i]=f[(s.a[i]+dis[j])%9];
sum=fun(t);
if(vis[sum]) continue;
t.step=s.step+1;
vis[sum]=1;
q.push(t);
}
}
}
for1(i,0,3){//交换相邻位
t=s;
swap(t.a[i],t.a[i+1]);
sum=fun(t);
if(vis[sum]) continue;
t.step=t.step+1;
vis[sum]=1;
q.push(t);
}
}
return -1;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("test.in","r",stdin);
freopen("test.out","w",stdout);
#endif
sf(T);
while(T--){
k=0;
char c;
for1(i,0,4){
cin>>c;
init[i]=c-'0';
}
for1(i,0,4){
cin>>c;
ans[i]=c-'0';
k=k*10+ans[i];
}
int res=bfs();
pf(res);
}
return 0;
}
DBFS:
#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <algorithm>
#include <iostream>
#include <iterator>
#include <sstream>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <set>
//#define ONLINE_JUDGE
#define eps 1e-6
#define INF 0x7fffffff //INT_MAX
#define inf 0x3f3f3f3f //int??????????????????
#define FOR(i,a) for((i)=0;i<(a);(i)++) //[i,a);
#define MEM(a) (memset((a),0,sizeof(a)))
#define sfs(a) scanf("%s",a)
#define sf(a) scanf("%d",&a)
#define sfI(a) scanf("%I64d",&a)
#define pf(a) printf("%d\n",a)
#define pfI(a) printf("%I64d\n",a)
#define pfs(a) printf("%s\n",a)
#define sfd(a,b) scanf("%d%d",&a,&b)
#define sft(a,b,c)scanf("%d%d%d",&a,&b,&c)
#define for1(i,a,b) for(int i=(a);i<b;i++)
#define for2(i,a,b) for(int i=(a);i<=b;i++)
#define for3(i,a,b)for(int i=(b);i>=a;i--)
#define MEM1(a) memset(a,0,sizeof(a))
#define MEM2(a) memset(a,-1,sizeof(a))
#define MEM3(a) memset(a,0x3f,sizeof(a))
#define MEMS(a) memset(a,'\0',sizeof(a))
#define LL __int64
const double PI = acos(-1.0);
template<class T> T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }
template<class T> T lcm(T a, T b) { return a / gcd(a, b) * b; }
template<class T> inline T Min(T a, T b) { return a < b ? a : b; }
template<class T> inline T Max(T a, T b) { return a > b ? a : b; }
using namespace std;
template<class T>
T Mint(T a, T b, T c) {
if (a>b) {
if (c>b)
return b;
return c;
}
if (c>a)
return a;
return c;
}
template<class T>
T Maxt(T a, T b, T c) {
if (a>b) {
if (c>a)
return c;
return a;
}
else if (c > b)
return c;
return b;
}
const int maxn=10010;
int T,n,m,k;
int init[4],ans[4],dis[2]={-1,1};
int f[9]={9,1,2,3,4,5,6,7,8};//数表
int d[maxn],vis[maxn];//标记数组
bool found;
struct node{
int a[4];
};
node s,e,t;
int sums,sume,sumt;
int fun(node p){//计算该数大小
int ans=0;
for1(i,0,4)
ans=ans*10+p.a[i];
return ans;
}
int bfs(queue<node> &q,bool flag){
s=q.front();
sums=fun(s);
q.pop();
if(flag){
for1(i,0,4){// // 每位数 加1或减1(若相应位置与答案不同)
if(s.a[i]!=ans[i]){
for1(j,0,2){
t=s;
t.a[i]=f[(s.a[i]+dis[j])%9];
sumt=fun(t);
if(vis[sumt]!=1){
if(vis[sumt]==2){
found=true;
return d[sumt]+d[sums]+1;
}
d[sumt]=d[sums]+1;
vis[sumt]=1;
q.push(t);
}
}
}
}
for1(i,0,3){//交换相邻位
t=s;
swap(t.a[i],t.a[i+1]);
sumt=fun(t);
if(vis[sumt]!=1){
if(vis[sumt]==2){
found=true;
return d[sumt]+d[sums]+1;
}
d[sumt]=d[sums]+1;
vis[sumt]=1;
q.push(t);
}
}
}
else {
for1(i,0,4){// // 每位数 加1或减1(若相应位置与答案不同)
if(s.a[i]!=init[i]){
for1(j,0,2){
t=s;
t.a[i]=f[(s.a[i]+dis[j])%9];
sumt=fun(t);
if(vis[sumt]!=2){
if(vis[sumt]==1){
found=true;
return d[sumt]+d[sums]+1;
}
d[sumt]=d[sums]+1;
vis[sumt]=2;
q.push(t);
}
}
}
}
for1(i,0,3){//交换相邻位
t=s;
swap(t.a[i],t.a[i+1]);
sumt=fun(t);
if(vis[sumt]!=2){
if(vis[sumt]==1){
found=true;
return d[sumt]+d[sums]+1;
}
d[sumt]=d[sums]+1;
vis[sumt]=2;
q.push(t);
}
}
}
return -1;
}
int DBFS(){
found=false;
MEM1(vis);
MEM1(d);
int res;
queue<node>q1;
queue<node>q2;
for1(i,0,4) s.a[i]=init[i];
for1(i,0,4) e.a[i]=ans[i];
sums=fun(s),sume=fun(e);
vis[sums]=1;vis[sume]=2;
q1.push(s);q2.push(e);
while(!q1.empty()||!q2.empty()){
if(!q1.empty()) res=bfs(q1,true);
if(found) return res;
if(!q2.empty()) res=bfs(q2,false);
if(found) return res;
}
return -1;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("test.in","r",stdin);
freopen("test.out","w",stdout);
#endif
sf(T);
while(T--){
char c;
for1(i,0,4){
cin>>c;
init[i]=c-'0';
}
for1(i,0,4){
cin>>c;
ans[i]=c-'0';
}
int res=DBFS();
pf(res);
}
return 0;
}