您的位置:首页 > 大数据 > 人工智能

2017 Multi-University Training Contest 10 1001 Admiral HDU 6171 (双向搜索 哈希)

2017-08-25 21:56 495 查看
题意: 给你一个高度为6的塔形数组,你每次只能将0与他上下相邻的某个数交换,问最少交换多少次可以变为初始状态,若需要的步数大于20,直接输出too difficult,初始状态为:



1 1 

2 2 2 

3 3 3 3 

4 4 4 4 4 

5 5 5 5 5 5

思路:因为最多走20步,单纯搜索时间复杂度4^20, 所以我们可以分别从当前状态和初始状态进行双向搜索降低复杂度,

每一步形成的状态可以把整个塔哈希成一个unsigned long long.

代码:

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
struct node
{
int val[6][6];
int r, c, k, step;
};
map<ll, int> book[2];

ll Hash(node x)
{
ll res = 0;
for(int i = 0; i < 6; i++)
for(int j = 0; j <= i; j++)
res = res*6+x.val[i][j];
return res;
}

int bfs(node s, node e)
{
queue<node> q;
book[0].clear(), book[1].clear();
s.k = 0, e.k = 1;
s.step = e.step = 0;
book[s.k][Hash(s)] = 0;
book[e.k][Hash(e)] = 0;
q.push(s), q.push(e);
while(!q.empty())
{
node u = q.front(); q.pop();
ll tmp = Hash(u);
if(book[!u.k].count(tmp))
{
if(book[!u.k][tmp]+u.step <= 20)
return book[!u.k][tmp]+u.step;
else continue;
}
if(u.step >= 10) continue;
int next[4][2] = {-1, -1, -1, 0, 1, 0, 1, 1};
for(int i = 0; i < 4; i++)
{
node t = u;
t.r += next[i][0];
t.c += next[i][1];
if(t.r >= 6 || t.r < 0 || t.c > t.r || t.c < 0) continue;
swap(t.val[t.r][t.c], t.val[u.r][u.c]);
tmp = Hash(t);
if(book[t.k].count(tmp)) continue;
t.step++;
book[t.k][tmp] = t.step;
q.push(t);
}
}
return -1;
}

int main(void)
{
int _;
cin >> _;
while(_--)
{
node s, e;
e.r = e.c = 0;
for(int i = 0; i < 6; i++)
{
for(int j = 0; j <= i; j++)
{
scanf("%d", &s.val[i][j]);
if(!s.val[i][j])
s.r = i, s.c = j;
e.val[i][j] = i;
}
}
int ans = bfs(s, e);
if(ans == -1) puts("too difficult");
else printf("%d\n", ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  HDU 多校 搜索
相关文章推荐