1312 : 搜索三·启发式搜索
2017-03-31 20:06
274 查看
时间限制:10000ms
单点时限:1000ms
内存限制:256MB
游戏的棋盘被分割成3x3的区域,上面放着标记有1~8八个数字的方形棋子,剩下一个区域为空。
游戏过程中,小Ho只能移动棋子到相邻的空区域上。当小Ho将8个棋子都移动到如下图所示的位置时,游戏就结束了。
小Hi:小Ho,你觉得如果用计算机来玩这个游戏应该怎么做?
小Ho:用计算机来玩么?我觉得应该是搜索吧,让我想一想。
提示:启发式搜索
接下来有t组数据,每组数据有3行,每行3个整数,包含0~8,每个数字只出现一次,其中0表示空位。
样例输入
样例输出
求最少多少步可以解决八数码问题。按照题目的指导,用康托展开的方法将一个状态映射到一个数,用这个数代表状态。然后用启发式搜索方法求出最少需要多少步可以解决问题。了解启发式搜索相关知识可以点击启发式搜索技术。
代码:
#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;
}
单点时限: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;
}
相关文章推荐
- hihocoder#1312 : 搜索三·启发式搜索(bfs+hash判重)
- hihoCoder #1312 : 搜索三·启发式搜索(A*, 康托展开)
- hiho一下 第一百周 #1312 : 搜索三·启发式搜索 【康托展开-压缩】
- 【hihocoder 1312】搜索三·启发式搜索(启发式搜索写法)
- 【hihocoder 1312】搜索三·启发式搜索(普通广搜做法)
- HIHO #1312 : 搜索三·启发式搜索
- 【郑轻oj】1312-Red and Black (搜索)
- hdu 1312 搜索
- HDU 1312:Red and Black(DFS搜索)
- Luogu 1312 【NOIP2011】玛雅游戏 (搜索)
- 一些重要的算法------启发式搜索,束搜索(beam search),二分查找算法 and so on............
- 深度搜索DFS hdu-1312
- HDU 1312 Red and Black 红与黑 搜索 dfs bfs
- 杭电 1312 Red and Black BFS 搜索
- hdu 1312 DFS深度搜索典型例题
- 杭电1312,搜索题
- [知识点]A*搜索(启发式搜索)
- HDU 1312 Red and Black (搜索)
- HDU 1312 Red and Black --- 入门搜索 DFS解法
- hud 1312 搜索