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的 ...
随机推荐
- Py中pyplot之subplot例子【转载】
转自:https://matplotlib.org/api/_as_gen/matplotlib.pyplot.subplot.html 1.有NaN的余弦图subplot import numpy ...
- xgb, lgb, Keras, LR(二分类、多分类代码)
preprocess # 通用的预处理框架 import pandas as pd import numpy as np import scipy as sp # 文件读取 def read_csv_ ...
- Java jdbc 操作数据库详解
原文地址https://www.cnblogs.com/huguodong/p/5910859.html JDBC(Java Data Base Connectivity,java数据库连接)是一种用 ...
- mysql主从数据库不同步的2种解决方法 (转载)
今天发现Mysql的主从数据库没有同步 先上Master库: mysql>show processlist; 查看下进程是否Sleep太多.发现很正常. show master status; ...
- Perl中的正则表达式(五)
正则表达式(Regular Expression),在Perl里边通常也叫做模式(Pattern),用来表示匹配(或不匹配)某个字符串的特征模板. 使用简单模式:若模式匹配的对象是$_的内容,只要把模 ...
- mysql插入和更新时自动更新为当前时间
创建表的时候添加 CREATE TABLE `tmp` ( `id` varchar(32) NOT NULL, `update_time ` timestamp NOT NULL DEFAUL ...
- Object-C-NSDictionary
存储对象都必须是id(对象类型)不能使基础类型 NSDictionary *scores=[[NSDictionary alloc]initWithObjectsAndKeys:@"89&q ...
- Java HTTP通信--Get与POST请求
一.JDK自带的http通信机制--java.net.URL package com.wjy; import java.io.BufferedReader; import java.io.Buffer ...
- python插入排序算法总结
插入排序算法总结: 插入算法的核心是 每次循环到一个数时,都认为这个数之前的数列都是排好序的,将一个数插入到已经排好序的有序数列中,从而得到一个新的.个数加一的有序数列. 过程:从第一个元素开始,第一 ...
- 设置(更改)Mysql 自增ID的起始值
SELECT * FROM segwords WHERE id>790511 DELETE FROM segwords WHERE id>790511 #下面这句是设置的 ALTER TA ...