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. react.js 之 create-react-app 命令行工具系统讲解

    react.js 教程之 create-react-app 命令行工具系统讲解 快速开始 npm install -g create-react-app create-react-app my-app ...

  2. MySQL读写分离-简单思考

    本文图片资源均来自互联网,没有干货,只是提供一种简单的思路. 基础原理 两台MySQL机器一个主,一个从实现数据实时同步比较简单,代码层面无需任何修改,添加一台机器简单配置配置即可,但是MySQL数据 ...

  3. DOM EVENT

    属性 此事件发生在何时... onabort 图像的加载被中断. onblur 元素失去焦点. onchange 域的内容被改变. onclick 当用户点击某个对象时调用的事件句柄. ondblcl ...

  4. java opencv使用相关

    Using OpenCV Java with Eclipse http://docs.opencv.org/2.4/doc/tutorials/introduction/java_eclipse/ja ...

  5. C++飞机大战

    #include<windows.h> #include"resource.h" #include<stdlib.h> #include<time.h ...

  6. 统计方法运行时间【Java实现】

    接口Command:定义命令的执行操作 package common; public interface Command { // 运行方法 void run(); } CommandRuntime ...

  7. pm2 观察报错时 pm2 start app.js --watch

    pm2 start app.js --watch[PM2][ERROR] Script already launched, add -f option to force re-execution

  8. linux基础命令---du

    du 以块为单位,显示当前目录下,所有目录.文件.子目录的磁盘使用情况.总结每个文件的磁盘使用情况,对目录进行递归处理 此命令的适用范围:RedHat.RHEL.Ubuntu.CentOS.SUSE. ...

  9. linux chkconfig 管理服务开机自启动

    chkconfig命令主要用来更新(启动或停止)和查询系统服务的运行级信息.谨记chkconfig不是立即自动禁止或激活一个服务,它只是简单的改变了符号连接. 使用语法:chkconfig [--ad ...

  10. Python之路----内置函数补充与匿名函数

    内置函数补充:reversed()保留原列表,返回一个反向的迭代器 l = [1,2,3,4,5] l.reverse() print(l) l = [1,2,3,4,5] l2 = reversed ...