http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=645
一道非常好的bfs的题,不同于树,它是隐式图,可能会回到之前的状态,所以需要用hash表保存每一步的状态,重点是双向bfs,对于超过10步的bfs,搜索空间会非常大,必须使用双向bfs,保存终止状态回走8步,起始状态走8步即可,代码如下:
#include<iostream>
#include<string.h>
#include<queue>
#include<cmath>
using namespace std;
#define MOD 99997
int f[] = {0,3,4,3,0,5,6,5,0,1,2,1,0,7,8,7,0,9,10,9,0,1,2,1};
void operation(int n, int *arr)
{
int a1, a2;
switch(n)
{
case 0: //Left Wheel Clockwise rotation
a1 = arr[10];
a2 = arr[11];
for(int i = 11; i > 1; --i)
{
arr[i] = arr[i-2];
}
arr[0] = a1;
arr[1] = a2;
for(int i = 23; i > 20; --i)
arr[i] = arr[i-12];
break;
case 1: //Right Wheel Clockwise rotation
a1 = arr[12];
a2 = arr[13];
for(int i = 12; i < 24; ++i)
arr[i] = arr[i+2];
arr[22] = a1;
arr[23] = a2;
for(int i = 11; i > 8; --i)
arr[i] = arr[i+12];
break;
case 2: //Left Wheel Counter-Clockwise rotation
a1 = arr[0];
a2 = arr[1];
for(int i = 0; i < 12; ++i)
arr[i] = arr[i+2];
arr[10] = a1;
arr[11] = a2;
for(int i = 23; i > 20; --i)
arr[i] = arr[i-12];
break;
case 3: //Right Wheel Counter-Clockwise rotation
a1 = arr[22];
a2 = arr[23];
for(int i = 23; i > 13; --i)
arr[i] = arr[i-2];
arr[12] = a1;
arr[13] = a2;
for(int i = 11; i > 8; --i)
arr[i] = arr[i+12];
break;
}
}
typedef struct State State;
struct State{
int arr[24];
int step;
string str;
bool operator == (const State &s)
{
for(int i = 0; i < 24; ++i)
if(arr[i] != s.arr[i])
return false;
return true;
}
};
vector<State> v[MOD];
vector<State> fv[MOD];
queue<State> q;
queue<State> qf;
bool flag;
State final;
int getBucket(State &s)
{
int hash = 1;
for(int i = 0; i < 24; ++i)
{
hash = s.arr[i] + hash*33;
hash = hash % MOD;
}
return hash;
}
bool exist(State &s, int which, State **n = NULL)
{
int bucket = getBucket(s);
if(which == 0) // v
{
int len = v[bucket].size();
for(int i = 0; i < len; ++i)
if(v[bucket][i] == s)
return true;
v[bucket].push_back(s);
return false;
}
else if(which == 1) //fv
{
int len = fv[bucket].size();
for(int i = 0; i < len; ++i)
if(fv[bucket][i] == s)
{
if(n != NULL)
*n = &fv[bucket][i];
return true;
}
return false;
}
}
void insert(State &s)
{
int bucket = getBucket(s);
fv[bucket].push_back(s);
}
void bfs()
{
while(!q.empty())
{
State n = q.front();
q.pop();
for(int i = 0; i < 4; ++i)
{
State tmp = n;
State *tmpn;
operation(i, tmp.arr);
tmp.str += i+1 + '0';
tmp.step += 1;
if(tmp.step > 8)
break;
if(final == tmp)
{
flag = true;
final = tmp;
return ;
}
if(exist(tmp, 1, &tmpn))
{
flag = true;
tmp.str += (*tmpn).str;
tmp.step += (*tmpn).step;
final = tmp;
return;
}
if(!exist(tmp, 0))
q.push(tmp);
}
}
}
void init(State &final)
{
qf.push(final);
while(!qf.empty())
{
State n = qf.front();
qf.pop();
for(int i = 3; i >= 0; --i)
{
State tmp = n;
operation(i, tmp.arr);
string str = "";
str += (i+2)%4 + 1 + '0';
tmp.str = str + tmp.str;
tmp.step += 1;
if(tmp.step > 8)
break;
if(!exist(tmp, 1))
{
insert(tmp);
qf.push(tmp);
}
}
}
}
int main()
{
int T;
cin>>T;
for(int i = 0; i < 24; ++i)
final.arr[i] = f[i];
final.step = 0;
final.str = "";
init(final);
while(T--)
{
for(int i = 0; i < 24; ++i)
final.arr[i] = f[i];
final.step = 0;
final.str = "";
State start;
for(int i = 0; i < 24; ++i)
{
cin>>start.arr[i];
}
start.step = 0;
start.str = "";
flag = false;
while(!q.empty())
q.pop();
for(int i = 0; i < MOD; ++i)
{
v[i].clear();
}
if(start == final)
{
cout<<"PUZZLE ALREADY SOLVED"<<endl;
continue;
}
State *tmp;
if(exist(start, 1, &tmp))
{
flag = true;
final = *tmp;
}
else
{
q.push(start);
bfs();
}
if(flag)
cout<<final.str<<endl;
else
cout<<"NO SOLUTION WAS FOUND IN 16 STEPS"<<endl;
}
return 0;
}
测试case:
4
输出:
4
PUZZLE ALREADY SOLVED
1434332334332323
NO SOLUTION WAS FOUND IN 16 STEPS
注意起始状态要先搜寻一遍是否已经在倒回的8步状态中了,否则会出现134这样的结果