您的位置:首页 > 其它

1312 : 搜索三·启发式搜索

2017-03-31 20:06 274 查看
时间限制:10000ms
单点时限:1000ms
内存限制:256MB

描述

在小Ho的手机上有一款叫做八数码的游戏,小Ho在坐车或者等人的时候经常使用这个游戏来打发时间。

游戏的棋盘被分割成3x3的区域,上面放着标记有1~8八个数字的方形棋子,剩下一个区域为空。


游戏过程中,小Ho只能移动棋子到相邻的空区域上。当小Ho将8个棋子都移动到如下图所示的位置时,游戏就结束了。


小Hi:小Ho,你觉得如果用计算机来玩这个游戏应该怎么做?

小Ho:用计算机来玩么?我觉得应该是搜索吧,让我想一想。

提示:启发式搜索

输入

第1行:1个正整数t,表示数据组数。1≤t≤8。

接下来有t组数据,每组数据有3行,每行3个整数,包含0~8,每个数字只出现一次,其中0表示空位。

输出

第1..t行:每行1个整数,表示该组数据解的步数。若无解输出"No Solution!"

样例输入
3
1 2 3
4 5 6
7 8 0
1 2 3
4 5 6
8 7 0
8 0 1
5 7 4
3 6 2

样例输出
0
No Solution!
25


求最少多少步可以解决八数码问题。按照题目的指导,用康托展开的方法将一个状态映射到一个数,用这个数代表状态。然后用启发式搜索方法求出最少需要多少步可以解决问题。了解启发式搜索相关知识可以点击启发式搜索技术。

代码:

#include <iostream>
#include <string>
#include <vector>
#include <climits>
#include <cmath>
#include <queue>
#include <set>
using namespace std;

int factor[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320};
vector<int> statnum(9);
vector<int> des({1, 2, 3, 4, 5, 6, 7, 8, 9});
int destination;

struct state
{
int f;
int g;
int h;
int x;
state(int f, int g, int h, int x):f(f), g(g), h(h), x(x){};
friend bool operator<(const state& a, const state& b)
{
if(a.f != b.f) return a.f > b.f;
else return a.g > b.g;
}
};

int cantor(const vector<int>& num)
{
int x = 0;
for(int i = 0; i < 9; ++i)
{
int tp = 0;
for(int j = i+1; j < 9; ++j)
{
if(num[i] > num[j]) tp++;
}
x += tp * factor[8-i];
}

return x;
}

vector<int> decantor(int x)
{
vector<int> num;
int a[9] = {0};
int used[9] = {0};

for(int i = 0; i < 9; ++i)
{
a[i] = x / factor[8-i];
x %= factor[8-i];

int cnt = 0;
for(int j = 0; j < 9; ++j)
{
if(!used[j])
{
cnt++;
if(a[i] + 1 == cnt)
{
num.push_back(j+1);
used[j] = 1;
break;
}
}
}
}

return num;
}

int getDist(int a, int b)
{
return (abs(a/3-b/3) + abs(a%3-b%3));
}

int getEvalution(vector<int> num)
{
int h = 0;
for(int i = 0; i < 9; ++i)
{
h += getDist(i, num[i]-1);
}
return h;
}

void solve()
{
priority_queue<state>openlist;
set<int>closelist;

int h = getEvalution(statnum);
openlist.push(state(h, 0, h, cantor(statnum)));
int step = 0;
bool hasSolution = false;

while(!openlist.empty())
{
state cur = openlist.top();
openlist.pop();
int x = cur.x;
closelist.insert(x);
if(destination == x)
{
hasSolution = true;
step = cur.g;
break;
}
vector<int> curstate = decantor(x);
for(int i = 0; i < 9; ++i)
{
if(curstate[i] == 9)
{
if(i % 3 != 2)
{
swap(curstate[i], curstate[i+1]);
int g = cur.g + 1;
int h = getEvalution(curstate);
int f = g + h;
int x = cantor(curstate);
if(closelist.find(x) == closelist.end())
{
openlist.push(state(f, g, h, x));
}
swap(curstate[i], curstate[i+1]);
}
if(i % 3 != 0)
{
swap(curstate[i], curstate[i-1]);
int g = cur.g + 1;
int h = getEvalution(curstate);
int f = g + h;
int x = cantor(curstate);
if(closelist.find(x) == closelist.end())
{
openlist.push(state(f, g, h, x));
}
swap(curstate[i], curstate[i-1]);
}
if(i / 3 != 2)
{
swap(curstate[i], curstate[i+3]);
int g = cur.g + 1;
int h = getEvalution(curstate);
int f = g + h;
int x = cantor(curstate);
if(closelist.find(x) == closelist.end())
{
openlist.push(state(f, g, h, x));
}
swap(curstate[i], curstate[i+3]);
}
if(i / 3 != 0)
{
swap(curstate[i], curstate[i-3]);
int g = cur.g + 1;
int h = getEvalution(curstate);
int f = g + h;
int x = cantor(curstate);
if(closelist.find(x) == closelist.end())
{
openlist.push(state(f, g, h, x));
}
swap(curstate[i], curstate[i-3]);
}
}
}
}

if(!hasSolution) cout << "No Solution!" << endl;
else cout << step << endl;
}

int main()
{
int n;
cin >> n;

destination = cantor(des);

while(n--)
{
for(int i = 0; i < 9; ++i)
{
cin >> statnum[i];
if(statnum[i] == 0) statnum[i] = 9;
}
solve();
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  heuristic search