HDU 1043 Eight(双向BFS+康托展开)
http://acm.hdu.edu.cn/showproblem.php?pid=1043
题意:给出一个八数码,求出到达指定状态的路径。
思路:路径寻找问题。在这道题里用到的知识点挺多的。第一次用双向BFS来做。
①双向BFS
在单向BFS的基础上,多建一个从终止状态开始搜索的队列,当然这个时候需要两个vis[]辅助数组,分别记录两个队列的访问情况,当两个队列相遇时即可终止循环。
②康托展开
X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! ,其中a[i]为当前未出现的元素中是排在第几个(从0开始)。这就是康托展开。
例:321的康托展开为:2*2!+1*1!+0*0!;
(数字3后比3小的数有2个,数字2后比2小的数有1个...依次类推)
③逆序数判断
每次交换两个数字逆序数的奇偶性不变,这个线代里有说过的,这样就可以根据最后状态的逆序数奇偶性来判断当前所给状态能给转换成功。不然的话好像是会超时的。
#include<iostream>
#include<string>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std; const int maxn = ;
const char* DIR1 = "udlr";
const char* DIR2 = "durl"; int fac[] = { , , , , , , , , }; //阶乘值 int x; //x的位置 int dir[] = { -, , -, }; int vis1[maxn];
int vis2[maxn]; char ss[] = "";
char str[]; struct Node
{
int x;
char str[];
}; struct Step
{
int cnt;
char dir;
}pre[maxn]; //记录路径 int sequence(char a[]) //计算康托展开值
{
int sum = ;
for (int i = ; i < ; i++)
{
int k = ;
for (int j = i + ; j < ; j++)
{
if (a[j] < a[i])
k++;
}
sum += fac[ - - i] * k;
}
return sum;
} void printfff(int x) //追溯到起点输出路径
{
if (pre[x].cnt == -) return;
printfff(pre[x].cnt);
cout << pre[x].dir;
} int judge(int x, int i) //判断是否越界
{
int xx = x / ; //行
int yy = x % ; //列
if (i == )
{
int yyy = yy + ;
if (yyy > ) return ;
}
if (i == )
{
int yyy = yy - ;
if (yyy < ) return ;
}
if (i == )
{
int xxx = xx + ;
if (xxx>) return ;
}
if (i == )
{
int xxx = xx - ;
if (xxx < ) return ;
}
return ;
} void bfs()
{
memset(vis1, , sizeof(vis1));
memset(vis2, , sizeof(vis2)); queue<Node> q1, q2;
Node p1, p2; int count = ;
strcpy(p1.str, str); //初始
p1.x = x; //初始x的位置
//cout << p1.str << endl;
strcpy(p2.str, ss); //终极
p2.x = ; //终极x的位置
//cout << p2.str << endl;
q1.push(p1);
q2.push(p2);
vis1[sequence(str)] = ;
vis2[sequence(ss)] = ;
pre[].cnt = -; //起点标记
pre[].cnt = -; //终点标记
while (!q1.empty() && !q2.empty())
{
Node u = q1.front();
q1.pop();
int p = sequence(u.str);
if (vis2[p]) //找到目标状态
{
printfff(vis1[p]);
int k = vis2[p];
while (pre[k].cnt != -)
{
cout << pre[k].dir;
k = pre[k].cnt;
}
cout << endl;
return;
}
else //未找到目标状态
{
Node u2;
for (int i = ; i < ; i++)
{
u2 = u;
if (!judge(u.x, i)) continue;
int xx = u.x + dir[i]; //x的新地址
swap(u2.str[u.x], u2.str[xx]);
u2.x = xx;
int v = sequence(u2.str);
if (vis1[v]) continue; //已访问
vis1[v] = ++count;
pre[count].dir = DIR1[i]; //记录方向
pre[count].cnt = vis1[p];
q1.push(u2);
}
} u = q2.front();
q2.pop();
p = sequence(u.str);
if (vis1[p])
{
printfff(vis1[p]);
int k = vis2[p];
while (pre[k].cnt != -)
{
cout << pre[k].dir;
k = pre[k].cnt;
}
cout << endl;
return;
}
else //未找到目标状态
{
Node u2;
for (int i = ; i < ; i++)
{
u2 = u;
if (!judge(u.x, i)) continue;
int xx = u.x + dir[i]; //x的新地址
swap(u2.str[u.x], u2.str[xx]);
u2.x = xx;
int v = sequence(u2.str);
if (vis2[v]) continue; //已访问
vis2[v] = ++count;
pre[count].dir = DIR2[i]; //记录方向
pre[count].cnt = vis2[p];
q2.push(u2);
}
}
}
cout << "unsolvable" << endl;
} int main()
{
//freopen("D:\\txt.txt", "r", stdin);
char s[];
while (gets(s))
{
int k = ;
int t = ;
for (int i = ; s[i] != NULL; i++)
{
if (s[i] == 'x') { str[k] = ''; x = k; }
else if (s[i] >= '' && s[i] <= '') str[k] = s[i];
else continue;
k++;
}
str[k] = '\0';
//int result = sequence(ss);
//cout << result << endl;
//cout << str << endl << ss << endl << x << endl; for (int i = ; i<; i++) //逆序数判断是否可行
{
if (str[i] == '')continue;
for (int j = ; j<i; j++)
{
if (str[j] == '')continue;
if (str[j]>str[i])t++;
}
}
if (t & ) cout << "unsolvable" << endl;
else bfs();
}
return ;
}
HDU 1043 Eight(双向BFS+康托展开)的更多相关文章
- hdu.1430.魔板(bfs + 康托展开)
魔板 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submis ...
- HDU 1043 Eight (A* + HASH + 康托展开)
Eight Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Sub ...
- Eight (HDU - 1043|POJ - 1077)(A* | 双向bfs+康拓展开)
The 15-puzzle has been around for over 100 years; even if you don't know it by that name, you've see ...
- HDU_1043 Eight 【逆向BFS + 康托展开 】【A* + 康托展开 】
一.题目 http://acm.hdu.edu.cn/showproblem.php?pid=1043 二.两种方法 该题很明显,是一个八数码的问题,就是9宫格,里面有一个空格,外加1~8的数字,任意 ...
- HDU 1043 Eight(反向BFS+打表+康托展开)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043 题目大意:传统八数码问题 解题思路:就是从“12345678x”这个终点状态开始反向BFS,将各 ...
- POJ 1077 && HDU 1043 Eight A*算法,bfs,康托展开,hash 难度:3
http://poj.org/problem?id=1077 http://acm.hdu.edu.cn/showproblem.php?pid=1043 X=a[n]*(n-1)!+a[n-1]*( ...
- 【HDU - 1043】Eight(反向bfs+康托展开)
Eight Descriptions: 简单介绍一下八数码问题:在一个3×3的九宫格上,填有1~8八个数字,空余一个位置,例如下图: 1 2 3 4 5 6 7 8 在上图中,由于右下角位置是空的 ...
- HDU 1430 魔板(康托展开+BFS+预处理)
魔板 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submis ...
- HDU - 1430 魔板 【BFS + 康托展开 + 哈希】
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1430 思路 我刚开始 想到的 就是 康托展开 但是这个题目是 多组输入 即使用 康托展开 也是会T的 ...
随机推荐
- vue.set的用法
Vue.set(this.food,'count',1) //就是给this.food里面添加一个count的属性,并且赋值为1
- 一起做RGB-D SLAM (2)
第二讲 从图像到点云 本讲中,我们将带领读者,编写一个将图像转换为点云的程序.该程序是后期处理地图的基础.最简单的点云地图即是把不同位置的点云进行拼接得到的. 当我们使用RGB-D相机时,会从相机里读 ...
- js定位当前位置的坐标经纬度和地点名称和天气
<script src="http://api.map.baidu.com/api?v=2.0&ak=s6vFvPKgaEnI2ImqBpKGDj0m">< ...
- PHP中header('content-type:text/html;charset="utf-8')和error_reporting()的作用
1.header PHP文件插入header("Content-type: text/html; charset=utf-8");相当于页面里面的<meta http-equ ...
- php 非递归实现分类树
本文实例讲述了php通过前序遍历树实现无需递归的无限极分类.分享给大家供大家参考.具体如下: 大家通常都是使用递归实现无限极分类都知道递归效率很低,下面介绍一种改进的前序遍历树算法,不适用递归实现无限 ...
- 使用点击二分图传导计算query-document的相关性
之前的博客中已经介绍了Ranking Relevance的一些基本情况(Click Behavior,和Text Match):http://www.cnblogs.com/bentuwuying/p ...
- R 简明教程
R 是一门统计语言.它有很多数据分析和挖掘程序包.可以用来统计.分析和制图. 你也可以在 LaTeX 文档中运行 R 命令. # 注释以 # 开始 # R 语言原生不支持 多行注释 # 但是你可以像这 ...
- Zookeeper学习记录(二):使用以及配置
zookeeper已经介绍了它的原理设计以及实现方式,我们接下来介绍zookeeper的使用方法以及简单配置. 下载 获取Zookeeper的发布包,从Apache下载映像中下载一个最新稳定版本. 单 ...
- B轮公司技术问题列表
B轮公司技术问题列表 1.异构系统的接口对接我们有自己的一套统一接口,但是需要与其它公司的接口做对接,但是各个公司的接口各不相同,有什么好的方式能够方便与各公司的接口做对接的同时我们这边也能尽量少或者 ...
- Js基础知识1-数组操作全解
数组操作全解 js变量类型 var string; var name = "student",age=12; //underfined.null.boolean.string.nu ...