主页面:http://blog.csdn.net/dolfamingo/article/details/77825569
(代码一直在精简完善……)
代码一:两个BFS, 两段代码; 用step控制“你一步, 我一步”。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
#define ms(a,b) memset((a),(b),sizeof((a)))
using namespace std;
typedef long long LL;
const int INF = 2e9;
const LL LNF = 9e18;
const int MOD = 1e9+7;
const int MAXN = 1e6+10;
struct node
{
int status;
int s[9];
int loc;
int step; //双向bfs需要记录第几步,才能做到“你一步,我一步”
};
int fac[9] = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320};
int dir1[4][2] = { -1,0, 1,0, 0,-1, 0,1 }; //正方向
char op1[4] = {'u', 'd', 'l', 'r' };
int dir2[4][2] = {0,1, 0,-1, 1,0, -1,0}; //反方向
char op2[4] = {'l', 'r', 'u', 'd' };
char path1[MAXN], path2[MAXN]; //1为正方向,2为反方向,以下皆如此
int pre1[MAXN], pre2[MAXN];
int cantor(int s[])
{
int sum = 0;
for(int i = 0; i<9; i++)
{
int num = 0;
for(int j = i+1; j<9; j++)
if(s[j]<s[i])
num++;
sum += num*fac[8-i];
}
return sum+1;
}
queue<node>q1, q2;
int vis1[MAXN], vis2[MAXN];
int bfs(node now)
{
ms(vis1,0);
ms(vis2,0);
while(!q1.empty()) q1.pop();
while(!q2.empty()) q2.pop();
now.status = cantor(now.s);
now.step = 0;
pre1[now.status] = -1;
vis1[now.status] = 1;
q1.push(now);
for(int i = 0; i<9; i++)
now.s[i] = i+1;
now.loc = 8;
now.status = cantor(now.s);
now.step = 0;
pre2[now.status] = -1;
vis2[now.status] = 1;
q2.push(now);
int time = 0; //计时器
while(!q1.empty() || !q2.empty())
{
time++;
while(!q1.empty())
{
if(q1.front().step==time) //时间到了,就让给对方
break;
now = q1.front();
q1.pop();
if(vis2[now.status]) //此状态已被对方访问过,则说明两者“接上了”
return now.status;
int x = now.loc/3;
int y = now.loc%3;
for(int i = 0; i<4; i++)
{
int xx = x + dir1[i][0];
int yy = y + dir1[i][1];
if(xx>=0 && xx<=2 && yy>=0 && yy<=2)
{
node tmp = now;
tmp.s[x*3+y] = tmp.s[xx*3+yy];
tmp.s[xx*3+yy] = 9;
tmp.status = cantor(tmp.s);
if(!vis1[tmp.status])
{
vis1[tmp.status] = 1;
tmp.loc = xx*3+yy;
tmp.step++;
path1[tmp.status] = op1[i];
pre1[tmp.status] = now.status;
q1.push(tmp);
}
}
}
}
while(!q2.empty())
{
if(q2.front().step==time) //时间到了,就让给对方
break;
now = q2.front();
q2.pop();
if(vis1[now.status]) //此状态已被对方访问过,则说明两者“接上了”
return now.status;
int x = now.loc/3;
int y = now.loc%3;
for(int i = 0; i<4; i++)
{
int xx = x + dir2[i][0];
int yy = y + dir2[i][1];
if(xx>=0 && xx<=2 && yy>=0 && yy<=2)
{
node tmp = now;
tmp.s[x*3+y] = tmp.s[xx*3+yy];
tmp.s[xx*3+yy] = 9;
tmp.status = cantor(tmp.s);
if(!vis2[tmp.status])
{
vis2[tmp.status] = 1;
tmp.loc = xx*3+yy;
tmp.step++;
path2[tmp.status] = op2[i];
pre2[tmp.status] = now.status;
q2.push(tmp);
}
}
}
}
}
return -1;
}
void Print1(int status) //输出正方向的路径
{
if(pre1[status]==-1) return;
Print1(pre1[status]);
putchar(path1[status]);
}
void Print2(int status) //输出反方向的路径
{
if(pre2[status]==-1) return;
putchar(path2[status]);
Print2(pre2[status]);
}
int main()
{
char tmp[50];
while(gets(tmp))
{
node beg;
int cnt = 0;
for(int i = 0; tmp[i]; i++)
{
if(tmp[i]==' ') continue;
if(tmp[i]=='x') beg.s[cnt] = 9, beg.loc = cnt++;
else beg.s[cnt++] = tmp[i]-'0';
}
int status = bfs(beg);
if(status==-1)
puts("unsolvable");
else
{
Print1(status); Print2(status); //输出路径
putchar('\n');
}
}
}
代码二:两个BFS, 两段代码; 用队列的大小控制“你一步, 我一步”。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
#define ms(a,b) memset((a),(b),sizeof((a)))
using namespace std;
typedef long long LL;
const int INF = 2e9;
const LL LNF = 9e18;
const int MOD = 1e9+7;
const int MAXN = 1e6+10;
struct node
{
int status;
int s[9];
int loc;
};
int fac[9] = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320};
int dir1[4][2] = { -1,0, 1,0, 0,-1, 0,1 }; //正方向
char op1[4] = {'u', 'd', 'l', 'r' };
int dir2[4][2] = {0,1, 0,-1, 1,0, -1,0}; //反方向
char op2[4] = {'l', 'r', 'u', 'd' };
char path1[MAXN], path2[MAXN]; //1为正方向,2为反方向,以下皆如此
int pre1[MAXN], pre2[MAXN];
int cantor(int s[])
{
int sum = 0;
for(int i = 0; i<9; i++)
{
int num = 0;
for(int j = i+1; j<9; j++)
if(s[j]<s[i])
num++;
sum += num*fac[8-i];
}
return sum+1;
}
queue<node>q1, q2;
int vis1[MAXN], vis2[MAXN];
int bfs(node now)
{
ms(vis1,0);
ms(vis2,0);
while(!q1.empty()) q1.pop();
while(!q2.empty()) q2.pop();
now.status = cantor(now.s);
pre1[now.status] = -1;
vis1[now.status] = 1;
q1.push(now);
for(int i = 0; i<9; i++)
now.s[i] = i+1;
now.loc = 8;
now.status = cantor(now.s);
pre2[now.status] = -1;
vis2[now.status] = 1;
q2.push(now);
while(!q1.empty() || !q2.empty())
{
int s1 = q1.size(); //当前队列中的结点步数是一样的,处理完这些结点,得到步数+1的结点
while(s1--)
{
now = q1.front();
q1.pop();
if(vis2[now.status]) //此状态已被对方访问过,则说明两者“接上了”
return now.status;
int x = now.loc/3;
int y = now.loc%3;
for(int i = 0; i<4; i++)
{
int xx = x + dir1[i][0];
int yy = y + dir1[i][1];
if(xx>=0 && xx<=2 && yy>=0 && yy<=2)
{
node tmp = now;
tmp.s[x*3+y] = tmp.s[xx*3+yy];
tmp.s[xx*3+yy] = 9;
tmp.status = cantor(tmp.s);
if(!vis1[tmp.status])
{
vis1[tmp.status] = 1;
tmp.loc = xx*3+yy;
path1[tmp.status] = op1[i];
pre1[tmp.status] = now.status;
q1.push(tmp);
}
}
}
}
int s2 = q2.size();
while(s2--)
{
now = q2.front();
q2.pop();
if(vis1[now.status]) //此状态已被对方访问过,则说明两者“接上了”
return now.status;
int x = now.loc/3;
int y = now.loc%3;
for(int i = 0; i<4; i++)
{
int xx = x + dir2[i][0];
int yy = y + dir2[i][1];
if(xx>=0 && xx<=2 && yy>=0 && yy<=2)
{
node tmp = now;
tmp.s[x*3+y] = tmp.s[xx*3+yy];
tmp.s[xx*3+yy] = 9;
tmp.status = cantor(tmp.s);
if(!vis2[tmp.status])
{
vis2[tmp.status] = 1;
tmp.loc = xx*3+yy;
path2[tmp.status] = op2[i];
pre2[tmp.status] = now.status;
q2.push(tmp);
}
}
}
}
}
return -1;
}
void Print1(int status) //输出正方向的路径
{
if(pre1[status]==-1) return;
Print1(pre1[status]);
putchar(path1[status]);
}
void Print2(int status) //输出反方向的路径
{
if(pre2[status]==-1) return;
putchar(path2[status]);
Print2(pre2[status]);
}
int main()
{
char tmp[50];
while(gets(tmp))
{
node beg;
int cnt = 0;
for(int i = 0; tmp[i]; i++)
{
if(tmp[i]==' ') continue;
if(tmp[i]=='x') beg.s[cnt] = 9, beg.loc = cnt++;
else beg.s[cnt++] = tmp[i]-'0';
}
int status = bfs(beg);
if(status==-1)
puts("unsolvable");
else
{
Print1(status); Print2(status); //输出路径
putchar('\n');
}
}
}
代码三:两个队列,调用一段BFS(),用队列的大小控制“你一步, 我一步”。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
#define ms(a,b) memset((a),(b),sizeof((a)))
using namespace std;
typedef long long LL;
const int INF = 2e9;
const LL LNF = 9e18;
const int MOD = 1e9+7;
const int MAXN = 1e6+10;
struct node
{
int status;
int s[9];
int loc;
};
int fac[9] = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320};
int dir[2][4][2] = { -1,0, 1,0, 0,-1, 0,1, 0,1, 0,-1, 1,0, -1,0}; //正方向
char op[2][4] = {'u', 'd', 'l', 'r' , 'l', 'r', 'u', 'd' };
char path[2][MAXN];
int pre[2][MAXN];
int cantor(int s[])
{
int sum = 0;
for(int i = 0; i<9; i++)
{
int num = 0;
for(int j = i+1; j<9; j++)
if(s[j]<s[i])
num++;
sum += num*fac[8-i];
}
return sum+1;
}
queue<node>q[2];
int vis[2][MAXN];
int bfs(int id)
{
int Size = q[id].size();
while(Size--)
{
node now = q[id].front();
q[id].pop();
if(vis[!id][now.status])
return now.status;
int x = now.loc/3;
int y = now.loc%3;
for(int i = 0; i<4; i++)
{
int xx = x + dir[id][i][0];
int yy = y + dir[id][i][1];
if(xx>=0 && xx<=2 && yy>=0 && yy<=2)
{
node tmp = now;
tmp.s[x*3+y] = tmp.s[xx*3+yy];
tmp.s[xx*3+yy] = 9;
tmp.status = cantor(tmp.s);
if(!vis[id][tmp.status])
{
vis[id][tmp.status] = 1;
tmp.loc = xx*3+yy;
path[id][tmp.status] = op[id][i];
pre[id][tmp.status] = now.status;
q[id].push(tmp);
}
}
}
}
return -1;
}
int solve(node now) //把两个bfs缩在一起写, 精简代码
{
ms(vis,0);
while(!q[0].empty()) q[0].pop();
while(!q[1].empty()) q[1].pop();
now.status = cantor(now.s);
pre[0][now.status] = -1;
vis[0][now.status] = 1;
q[0].push(now);
for(int i = 0; i<9; i++)
now.s[i] = i+1;
now.loc = 8;
now.status = cantor(now.s);
pre[1][now.status] = -1;
vis[1][now.status] = 1;
q[1].push(now);
int time = 0, ret;
while(!q[0].empty() ||!q[1].empty())
{
ret = bfs(0);
if(ret!=-1) return ret;
ret = bfs(1);
if(ret!=-1) return ret;
time++;
}
return -1;
}
void Print1(int status) //输出正方向的路径
{
if(pre[0][status]==-1) return;
Print1(pre[0][status]);
putchar(path[0][status]);
}
void Print2(int status) //输出反方向的路径
{
if(pre[1][status]==-1) return;
putchar(path[1][status]);
Print2(pre[1][status]);
}
int main()
{
char tmp[50];
while(gets(tmp))
{
node beg;
int cnt = 0;
for(int i = 0; tmp[i]; i++)
{
if(tmp[i]==' ') continue;
if(tmp[i]=='x') beg.s[cnt] = 9, beg.loc = cnt++;
else beg.s[cnt++] = tmp[i]-'0';
}
int status = solve(beg);
if(status==-1)
puts("unsolvable");
else
{
Print1(status); Print2(status); //输出路径
putchar('\n');
}
}
}
代码四:一个队列(将正反两方向的结点都丢进同一个队列, 保证了“你一步我一步”), 一段BFS。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
#define ms(a,b) memset((a),(b),sizeof((a)))
using namespace std;
typedef long long LL;
const int INF = 2e9;
const LL LNF = 9e18;
const int MOD = 1e9+7;
const int MAXN = 1e6+10;
struct node
{
int status;
int s[9];
int loc;
int id; //id标记正反方向
};
int fac[9] = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320};
int dir[2][4][2] = { -1,0, 1,0, 0,-1, 0,1, 0,1, 0,-1, 1,0, -1,0}; //正方向
char op[2][4] = {'u', 'd', 'l', 'r' , 'l', 'r', 'u', 'd' };
char path[2][MAXN];
int pre[2][MAXN];
int cantor(int s[])
{
int sum = 0;
for(int i = 0; i<9; i++)
{
int num = 0;
for(int j = i+1; j<9; j++)
if(s[j]<s[i])
num++;
sum += num*fac[8-i];
}
return sum+1;
}
queue<node>que;
int vis[2][MAXN];
int bfs(node now) //把两个bfs缩在一起写, 精简代码
{
ms(vis,0);
while(!que.empty()) que.pop();
now.status = cantor(now.s);
now.id = 0;
pre[0][now.status] = -1;
vis[0][now.status] = 1;
que.push(now);
for(int i = 0; i<9; i++)
now.s[i] = i+1;
now.loc = 8;
now.status = cantor(now.s);
now.id = 1;
pre[1][now.status] = -1;
vis[1][now.status] = 1;
que.push(now);
while(!que.empty())
{
node now = que.front();
que.pop();
if(vis[!now.id][now.status])
return now.status;
int x = now.loc/3;
int y = now.loc%3;
for(int i = 0; i<4; i++)
{
int xx = x + dir[now.id][i][0];
int yy = y + dir[now.id][i][1];
if(xx>=0 && xx<=2 && yy>=0 && yy<=2)
{
node tmp = now;
tmp.s[x*3+y] = tmp.s[xx*3+yy];
tmp.s[xx*3+yy] = 9;
tmp.status = cantor(tmp.s);
if(!vis[now.id][tmp.status])
{
vis[now.id][tmp.status] = 1;
tmp.loc = xx*3+yy;
path[now.id][tmp.status] = op[now.id][i];
pre[now.id][tmp.status] = now.status;
que.push(tmp);
}
}
}
}
}
void Print1(int status) //输出正方向的路径
{
if(pre[0][status]==-1) return;
Print1(pre[0][status]);
putchar(path[0][status]);
}
void Print2(int status) //输出反方向的路径
{
if(pre[1][status]==-1) return;
putchar(path[1][status]);
Print2(pre[1][status]);
}
int main()
{
char tmp[50];
while(gets(tmp))
{
node beg;
int cnt = 0;
for(int i = 0; tmp[i]; i++)
{
if(tmp[i]==' ') continue;
if(tmp[i]=='x') beg.s[cnt] = 9, beg.loc = cnt++;
else beg.s[cnt++] = tmp[i]-'0';
}
int status = bfs(beg);
if(status==-1)
puts("unsolvable");
else
{
Print1(status); Print2(status); //输出路径
putchar('\n');
}
}
}