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+康托展开)的更多相关文章

  1. hdu.1430.魔板(bfs + 康托展开)

    魔板 Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submis ...

  2. HDU 1043 Eight (A* + HASH + 康托展开)

    Eight Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Sub ...

  3. 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 ...

  4. HDU_1043 Eight 【逆向BFS + 康托展开 】【A* + 康托展开 】

    一.题目 http://acm.hdu.edu.cn/showproblem.php?pid=1043 二.两种方法 该题很明显,是一个八数码的问题,就是9宫格,里面有一个空格,外加1~8的数字,任意 ...

  5. HDU 1043 Eight(反向BFS+打表+康托展开)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043 题目大意:传统八数码问题 解题思路:就是从“12345678x”这个终点状态开始反向BFS,将各 ...

  6. 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]*( ...

  7. 【HDU - 1043】Eight(反向bfs+康托展开)

    Eight Descriptions: 简单介绍一下八数码问题:在一个3×3的九宫格上,填有1~8八个数字,空余一个位置,例如下图: 1 2 3 4 5 6 7 8   在上图中,由于右下角位置是空的 ...

  8. HDU 1430 魔板(康托展开+BFS+预处理)

    魔板 Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submis ...

  9. HDU - 1430 魔板 【BFS + 康托展开 + 哈希】

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1430 思路 我刚开始 想到的 就是 康托展开 但是这个题目是 多组输入 即使用 康托展开 也是会T的 ...

随机推荐

  1. 008-ant design roadhogrc 打包

    一.概述 1.1.官方地址以及说明 由于 Ant Design Pro 底层使用的 roadhog 工具,已经将复杂的流程封装完毕,对于大部分场景,构建打包文件只需要一个命令 roadhog buil ...

  2. 使用客户端等远程连接mysql数据库

    1:  远程数据库(D1)数据: 数据库用户:root,数据库密码:root,数据库ip 内网地址  192.168.100.91,数据库端口 3306 本地主机:ip  192.168.127.1 ...

  3. 启动rabbitmq,提示ERROR: node with name "rabbit" already running on "localhost"

    ➜ ~ rabbitmq-server ERROR: node with name "rabbit" already running on "localhost" ...

  4. c++多态特性总结

    将父类比喻为电脑的外设接口,子类比喻为外设,现在我有移动硬盘.U盘以及MP3,它们3个都是可以作为存储但是也各不相同.如果我在写驱动的时候,我用个父类表示外设接口,然后在子类中重写父类那个读取设备的虚 ...

  5. 【Win7 x64】+【annaconda3】+ 【python3.5.2】+【tensorflow-gpu】 [最终配置 gtx 940mx + Cuda8.0+cudnn v5.1 + tensorflow-gpu1.0.0 ]

    1.安装cuda Toolkit 和cudnn (百度云可下载,版本需要对应) 2.配置环境变量: 3.安装cudnn(需要拷贝一些dll和lib来进行配置) 4.进入cmd,找到anaconda3的 ...

  6. MVC增加操作日志

    在后台管理中,有一些操作是需要增加操作日志的,尤其是对一些比较敏感的金额类的操作,比如商城类的修改商品金额.删除商品.赠送金额等人工的操作.日志中记录着相关操作人的操作信息,这样,出了问题也容易排查. ...

  7. DW课堂练习 用所学的知识去制作一个 (邮箱的注册页面)

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  8. 分布式一致性Hash

    转载: https://blog.csdn.net/bntX2jSQfEHy7/article/details/79549368 为什么要有Hash一致性算法?就像以前介绍为什么要有Spring一样, ...

  9. MSF渗透测试-CVE-2017-11882(MSOffice漏洞)

    1.测试环境 2.测试前准备 3.测试过程 -3.1虚拟机环境测试 -3.2局域网靶机测试 4.测试感想 1.测试环境 攻击机: OS:kail IP:192.168.15.132/192.168.1 ...

  10. Python 在序列上跟踪索引和值

    内置的enumerate() 函数可以很好的解决这个问题 >>> my_list = ['a', 'b', 'c'] >>> for idx, val in enu ...