非常经典的8数码问题,主要采用的算法是人工智能中的“有序搜索算法”,也有人称之为A算法。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <set>
#include <string>
using namespace std;
const int LEN = 9;
struct PStatus
{
string pos;//位置信息
int index;//'x'的坐标位置
PStatus *parent;//指向父状态
char direction;//l,r,u,d
int height;//高度
int f;//f值
};
PStatus bStatus;
PStatus gStatus = {"12345678x"};
int getWrongPoses(string pos)//错放棋子个数
{
int sum = 0;
for (int i = 0; i < pos.size(); ++i)
if (gStatus.pos[i] != pos[i])
sum++;
return sum;
}
bool cmp1(PStatus* first,PStatus* second)
{
int r = first->pos.compare(second->pos);
if (r < 0)return false;
if (r > 0)return true;
return false;
}
set<PStatus*,bool (*)(PStatus* ,PStatus* )> closed(cmp1);
bool cmp2(PStatus* first,PStatus* second)
{
if (first->f < second->f)return true;
if (first->f > second->f)return false;
return false;
}
multiset<PStatus*,bool (*)(PStatus* ,PStatus* )> open(cmp2);
bool isInClosed(PStatus* status)
{
if (closed.find(status) != closed.end())return true;
return false;
}
bool isInOpen(PStatus* status)
{
multiset<PStatus*,bool (*)(PStatus* ,PStatus* )>::iterator it = open.begin();
for (; it != open.end(); ++it)
if (status->pos == (*it)->pos)
return true;
return false;
}
string bfs()
{
PStatus *ps,*np;
int i;
open.insert(&bStatus);
while (open.size() > 0)
{
ps = *open.begin();
if (ps->pos == gStatus.pos)//找到答案
{
string result = "";
while(ps != NULL)
{
if (ps->direction != 'z')
result = ps->direction + result;
ps = ps->parent;
}
return result;
}
open.erase(open.begin());
closed.insert(ps);
for (i = 0; i < 4; ++i)
{
switch(i)
{
case 0://left
if (ps->direction != 'r' && ps->index%3 != 0)
{
np = new PStatus;
np->pos = ps->pos;
swap(np->pos[ps->index], np->pos[ps->index-1]);
if (!isInClosed(np) && !isInOpen(np))
{
np->parent = ps;
np->index = ps->index - 1;
np->direction = 'l';
//np->height = ps->height + 1;
//np->f = np->height + getWrongPoses(np->pos);
np->f = getWrongPoses(np->pos);
open.insert(np);
}
else
delete np;
}
break;
case 1://right
if (ps->direction != 'l' && ps->index%3 != 2)
{
np = new PStatus;
np->pos = ps->pos;
swap(np->pos[ps->index], np->pos[ps->index+1]);
if (!isInClosed(np) && !isInOpen(np))
{
np->parent = ps;
np->index = ps->index+1;
np->direction = 'r';
//np->height = ps->height + 1;
//np->f = np->height + getWrongPoses(np->pos);
np->f = getWrongPoses(np->pos);
open.insert(np);
}
else
delete np;
}
break;
case 2://up
if (ps->direction != 'd' && (ps->index - ps->index%3) > 2)
{
np = new PStatus;
np->pos = ps->pos;
swap(np->pos[ps->index], np->pos[ps->index-3]);
if (!isInClosed(np) && !isInOpen(np))
{
np->parent = ps;
np->index = ps->index - 3;
np->direction = 'u';
//np->height = ps->height + 1;
//np->f = np->height + getWrongPoses(np->pos);
np->f = getWrongPoses(np->pos);
open.insert(np);
}
else
delete np;
}
break;
case 3://down
if (ps->direction != 'u' && ps->index < 6)
{
np = new PStatus;
np->pos = ps->pos;
swap(np->pos[ps->index], np->pos[ps->index+3]);
if (!isInClosed(np) && !isInOpen(np))
{
np->parent = ps;
np->index = ps->index +3;
np->direction = 'd';
//np->height = ps->height + 1;
//np->f = np->height + getWrongPoses(np->pos);
np->f = getWrongPoses(np->pos);
open.insert(np);
}
else
delete np;
}
break;
}
}
}
return "unsolvable";
}
//两个状态之间是否可达,可以通过计算两者的逆序值,若两者奇偶性相同则可达,不然两个状态不可达
bool solvable(string pos,int index)
{
pos.erase(index,1);
int sum = 0;
for (int i = 1; i < pos.size(); ++i)
{
for (int j = 0; j < i; ++j)
if (pos[i] < pos[j])
sum += 1;
}
if (sum%2 == 0)return true;
else return false;
}
int main()
{
freopen("in.txt","r",stdin);
char ch;
for (int i = 0; i < LEN; ++i)
{
cin>>ch;
bStatus.pos += ch;
if (ch == 'x')bStatus.index = i;
}
if(!solvable(bStatus.pos,bStatus.index))
cout<<"unsolvable"<<endl;
else
{
bStatus.parent = NULL;
bStatus.direction = 'z';//没有方向
bStatus.height = 0;
bStatus.f = getWrongPoses(bStatus.pos) + bStatus.height;
cout<<bfs()<<endl;
}
}
测试数据
2 3 4 1 5 x 7 6 8
1 2 3 7 6 4 8 x 5
1 2 3 7 x 4 8 6 5
1 2 3 4 5 6 7 x 8
1 2 7 4 5 6 3 8 x
下面这个版本速度太慢,但是对于STL的学习还是不错的。
//#include <iostream>
//#include <cstdio>
//#include <algorithm>
//#include <list>
//#include <string>
//using namespace std;
//
//const int LEN = 9;
//struct PStatus
//{
// string pos;//位置信息
// int index;//'x'的坐标位置
// PStatus *parent;//指向父状态
// char direction;//l,r,u,d
//};
//
//template<class T1,class T2,class T3>
//struct fcmp:public std::binary_function<T1,T2,T3>
//{
// T3 operator()(T1 first, T2 second) const
// {
// return first->pos == second->pos;
// }
//};
//
//PStatus bStatus;
//PStatus gStatus = {"12345678x"};
//list<PStatus*> open,closed;
//
//bool isInClosed(PStatus* status)
//{
// list<PStatus*>::iterator it = find_if(closed.begin(),closed.end(),
// bind2nd(fcmp<PStatus*, PStatus*,bool>(), status));
// if (it != closed.end())return true;
// return false;
//}
//
//bool isInOpen(PStatus* status)
//{
// list<PStatus*>::iterator it = find_if(open.begin(),open.end(),
// bind2nd(fcmp<PStatus*, PStatus*,bool>(), status));
// if (it != open.end())return true;
// return false;
//}
//
//void bfs()
//{
// PStatus *ps,*np;
// int i;
// open.push_back(&bStatus);
// while (open.size() > 0)
// {
// ps = open.front();
// if (ps->pos == gStatus.pos)//找到答案
// {
// while(ps != NULL)
// {
// cout<<ps->direction;
// ps = ps->parent;
// }
// return;
// }
//
// open.pop_front();
// closed.push_back(ps);
//
// for (i = 0; i < 4; ++i)
// {
// switch(i)
// {
// case 0://left
// if (ps->direction != 'r' && ps->index%3 != 0)
// {
// np = new PStatus;
// np->pos = ps->pos;
// swap(np->pos[ps->index], np->pos[ps->index-1]);
// if (!isInClosed(np) && !isInOpen(np))
// {
// np->parent = ps;
// np->index = ps->index - 1;
// np->direction = 'l';
//
// open.push_back(np);
// }
// else
// delete np;
// }
// break;
// case 1://right
// if (ps->direction != 'l' && ps->index%3 != 2)
// {
// np = new PStatus;
// np->pos = ps->pos;
// swap(np->pos[ps->index], np->pos[ps->index+1]);
// if (!isInClosed(np) && !isInOpen(np))
// {
// np->parent = ps;
// np->index = ps->index+1;
// np->direction = 'r';
//
// open.push_back(np);
// }
// else
// delete np;
// }
// break;
// case 2://up
// if (ps->direction != 'd' && (ps->index - ps->index%3) > 2)
// {
// np = new PStatus;
// np->pos = ps->pos;
// swap(np->pos[ps->index], np->pos[ps->index-3]);
// if (!isInClosed(np) && !isInOpen(np))
// {
// np->parent = ps;
// np->index = ps->index - 3;
// np->direction = 'u';
//
// open.push_back(np);
// }
// else
// delete np;
// }
// break;
// case 3://down
// if (ps->direction != 'u' && ps->index < 6)
// {
// np = new PStatus;
// np->pos = ps->pos;
// swap(np->pos[ps->index], np->pos[ps->index+3]);
// if (!isInClosed(np) && !isInOpen(np))
// {
// np->parent = ps;
// np->index = ps->index +3;
// np->direction = 'd';
//
// open.push_back(np);
// }
// else
// delete np;
// }
// break;
// }
// }
// }
//
// cout<<"unsolvable"<<endl;
//}
//
//bool solvable(string pos,int index)
//{
// pos.erase(index,1);
// int sum = 0;
// for (int i = 1; i < pos.size(); ++i)
// {
// for (int j = 0; j < i; ++j)
// if (pos[i] < pos[j])
// sum += 1;
// }
// if (sum%2 == 0)return true;
// else return false;
//}
//
//int main()
//{
// freopen("in.txt","r",stdin);
// char ch;
// for (int i = 0; i < LEN; ++i)
// {
// cin>>ch;
// bStatus.pos += ch;
// if (ch == 'x')bStatus.index = i;
// }
//
// if(!solvable(bStatus.pos,bStatus.index))
// cout<<"unsolvable"<<endl;
// else
// {
// bStatus.parent = NULL;
// bStatus.direction = 'z';//没有方向
// bfs();
// }
//
//}