poj 1077 bfs+康托展开(8数码问题)

黑猫带你学eMMC协议第2篇:eMMC部分相关名词释义 1 前言 1.1 声明 本文依据eMMC JEDEC5.1、网络资料及个人工作经验整理而成,如有错误请留言。 本文结合eMMC JEDEC5.1协议手册查看效果更佳。 1.2 本文背景 本文关键词不包括emmc jedec5.1协议第3章节:《Terms and definitions》内容。关于emmc协议层的关键词,直接查阅spec相关章节即可,清晰明了,此处没必要再列出。 本文为本人工作学习中常听到或常用到关乎于emmc/flash的一些关键词合集,没有固定分类,不需要强行记忆,供查询使用。 1. 阅读详情

题意:8数码问题

思路:此题多种方法可解,例如BFS、A* 、 IDA*等等。

法一:bfs,用康托展开来标记判重。所谓康托展开就是将1~n!个整数与n的全排列一一对应起来的一种方法,一种排列的值为i表示这种排列的字典序为第i小。

#include <stdio.h>
#include <string.h>
#define N 362880
int s[9];
int fact[9] = {40320,5040,720,120,24,6,2,1,1};
int ori[4][2] = {{0,-1},{-1,0},{0,1},{1,0}};
int flag[N];
struct queue{
	int s[9],dig,flag,pre;
}q[N];
int end;
int contor(int s[9]){//康托展开
	int i,j,res,temp;
	for(i = 0,res=0;i<8;i++){
		for(j = i+1,temp=0;j<9;j++)
			if(s[j]<s[i])
				temp++;
		res += temp * fact[i];
	}
	return res;
}
int check(int x,int y){
	if(x<0||y<0||x>2||y>2)
		return 0;
	return 1;
}
void print(i){
	int j;
	if(i!=0){
		print(q[i].pre);
		if(q[i].flag == 0)
			putchar('l');
		else if(q[i].flag == 1)
			putchar('u');
		else if(q[i].flag == 2)
			putchar('r');
		else if(q[i].flag == 3)
			putchar('d');
	}
}
int bfs(){
	struct queue now; 
	int i,j,front,rear,x,y,xx,yy,temp,t[9];
	front = -1;
	rear = 0;
	while(front < rear){
		now = q[++front];
		x = now.dig/3;
		y = now.dig%3;
		for(i = 0;i<4;i++){
			xx = x+ori[i][0];
			yy = y+ori[i][1];
			if(check(xx,yy)){
				for(j = 0;j<9;j++)
					t[j] = now.s[j];
				t[3*x+y] = t[3*xx+yy];
				t[3*xx+yy] = 9;
				temp = contor(t);
				if(!flag[temp]){
					flag[temp] = 1;
					q[++rear].dig = 3*xx+yy;
					for(j = 0;j<9;j++)
						q[rear].s[j] = t[j];
					q[rear].pre = front;
					q[rear].flag = i;
					if(temp == end){
						print(rear);
						return 1;
					}
				}
			}	
		}
	}
	return 0;
}
int main(){
	int i,j,k;
	char ch;	
	freopen("a.txt","r",stdin);
	memset(flag,0,sizeof(flag));
	end = 0;
	for(i = 0;i<9;i++){
		while((ch = getchar()) && ch==' ');
		if(ch == 'x'){
			s[i] = 9;
			q[0].dig = i;
		}
		else
			s[i] = ch - '0';
	}
	i = contor(s);
	flag[i] = 1;
	for(i = 0;i<9;i++)
		q[0].s[i] = s[i];
	if(!bfs())
		printf("unsolvable");
	putchar('\n');
	return 0;
}


法二:IDA*。IDA*算法是A*算法和迭代加深算法的结合。
迭代加深算法是在dfs搜索算法的基础上逐步加深搜索的深度,它避免了广度优先搜索占用搜索空间太大的缺点,也减少了深度优先搜索的盲目性。它主要是在递归搜索函数的开头判断当前搜索的深度是否大于预定义的最大搜索深度,如果大于,就退出这一层的搜索,如果不大于,就继续进行搜索。这样最终获得的解必然是最优解。
而在A*算法中,我们通过使用合理的估价函数,然后在获得的子节点中选择fCost最小的节点进行扩展,以此完成搜索最优解的目的。但是A*算法中,需要维护关闭列表和开放列表,需要对扩展出来的节点进行检测,忽略已经进入到关闭列表中的节点(也就是所谓的“已经检测过的节点”),另外也要检测是否与待扩展的节点重复,如果重复进行相应的更新操作。所以A*算法主要的代价花在了状态检测和选择代价最小节点的排序上,这个过程中占用的内存是比较大的,一般为了提高效率都是使用hash进行重复状态检测。
而IDA*算法具有如下的特点:综合了A*算法的人工智能性和回溯法对空间的消耗较少的优点,在一些规模很大的搜索问题中会起意想不到的效果。它的具体名称是Iterative Deepening A*, 1985年由Korf提出。该算法的最初目的是为了利用深度搜索的优势解决广度A*的空间问题,其代价是会产生重复搜索。归纳一下,IDA*的基本思路是:首先将初始状态结点的H值设为阈值maxH,然后进行深度优先搜索,搜索过程中忽略所有H值大于maxH的结点;如果没有找到解,则加大阈值maxH,再重复上述搜索,直到找到一个解。在保证H值的计算满足A*算法的要求下,可以证明找到的这个解一定是最优解。在程序实现上,IDA* 要比 A* 方便,因为不需要保存结点,不需要判重复,也不需要根据H值对结点排序,占用空间小。 而IDA*算法中也使用合适的估价函数,来评估与目标状态的距离。
在一般的问题中是这样使用IDA*算法的,当前局面的估价函数值+当前的搜索深度 > 预定义的最大搜索深度时,就进行剪枝。

#include <cstdio>
#include <cmath>
#include <cstdlib>
using namespace std;
int s[10];
int path[10000],len = -1;
int ori[9][4] = {
    {-1,1,3,-1},
    {-1,2,4,0},
    {-1,-1,5,1},
    {0,4,6,-1},
    {1,5,7,3},
    {2,-1,8,4},
    {3,7,-1,-1},
    {4,8,-1,6},
    {5,-1,-1,7},
};
void swap(int &x,int &y){
    int tmp = x;
    x = y;
    y = tmp;
}
int h(){
    int sum = 0;
    for(int i = 0;i<8;i++){
        if(s[i] == 8)
            continue;
        sum += abs(i/3 - s[i]/3) + abs(i%3 - s[i]%3);
    }
    return sum;
}
bool has_solution(){
    int sum = 0;
    for(int i = 1;i<9;i++){
        if(s[i] == 8) continue;
        for(int j = 0;j<i;j++)
            if(s[j] != 8 && s[i] < s[j])
                sum++;
    }
    return (sum&1) == 0;
}
bool is_solution(){
    for(int i = 0;i<8;i++)
        if(s[i] != i)
            return false;
    return true;
}
bool IDASTAR(int now, int limit, int x){
    if(now >= limit)
        return is_solution();
    for(int i = 0;i<4;i++){
        int xx = ori[x][i];
        if(xx == -1)
            continue;
        if(len>=0 && abs(path[len]-i) == 2)
            continue;
        swap(s[xx], s[x]);
        path[++len] = i;
        if(now+h() <= limit && IDASTAR(now+1, limit, xx))
            return true;
        --len;
        swap(s[xx], s[x]);
    }
    return false;
}
void print(){
    for(int i = 0;i<=len;i++){
        if(path[i] == 0)
            putchar('u');
        else if(path[i] == 1)
            putchar('r');
        else if(path[i] == 2)
            putchar('d');
        else
            putchar('l');
    }
    putchar('\n');
}
int main(){
    char ch;
    int state=0, i = 0;
    while((ch = getchar()) != EOF){
        if(ch == ' ' || ch == '\t' || ch == '\n') continue;
        if(ch == 'x'){
            state = i;
            s[i++] = 8;
        }else
            s[i++] = ch-'1';
    }
    if(has_solution()){
        int upper = h();
        while(!IDASTAR(0, upper, state))
            upper++;
        print();
    }else
        printf("unsolvable\n");
    return 0;
}


【软考之软件设计师】学习笔记 interface 接口implements 实现接口(与接口配套使用)接口里要是有方法定义,子类就会实现。 阅读详情

相关推荐

华南理工大学电子与信息学院23年预推免复试面试经验贴

华南理工大学电子与信息学院23年预推免复试面试经验贴

Scut_Ty的博客 3298

八数码问题之康拓展开求解

八数码问题描述: 在九宫格里放在1到8共8个数字还有一个是空格,与空格相邻的数字可以移动到空格的位置,问给定的状态最少需要几步能到达目标状态(用0表示空格)! 类似于华容道,只不过华容道的最终状态是: 123 456 780 解题思路: 这个问题正常想法是直接上BFS,但是难点就在于在bfs时,改用什么样的状态来保存当前状态以及搜索过的状态。最初的想法是用一个9!大小的数组或者set...

sjs_caomei的博客 578

深入解析AutoConfigURL劫持:从注册表权限到一键修复

本文深入解析了AutoConfigURL劫持的原理,揭示其通过篡改注册表权限锁定浏览器设置的机制。文章提供了从手动修复注册表权限到使用一键修复工具的详细解决方案,并指导用户进行DNS检查与病毒查杀,以彻底根除此类顽固劫持问题。

weixin_29229989的博客 768

康托展开(八数码问题)

把一个整数X展开成如下形式: X=a[n]∗*(n-1)!+a[n-1]∗*(n-2)!+…+a[i]*(i-1)!+…+a[2]*1!+a[1]*0![1] 其中a[i]为当前未出现的元素中是排在第几个(从0开始),并且0<=a[i]<<i(1<=i<=n)

forezxl的博客 2417

STM32使用HAL库实现ModbusRTU主站核心要点

深入解析STM32如何利用HAL库高效实现ModbusRTU主站通信,重点讲解串口配置、定时控制与modbusrtu协议帧的构建方法,提升嵌入式通信稳定性与实时性。

weixin_42668301的博客 373

SAP OData 开发从入门到提高教程的目录

笔者 18 年的 SAP 技术开发生涯,对 SAP OData 服务的开发,测试,发布,部署,测试,及基于各种不同 SAP 技术实现的 OData 服务的幕后技术实现细节和使用场合,均有着深入的研究。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 7246

康托展开求八数码问题

/* 问题描述: 目标状态为: 1 2 3 4 5 6 7 8 0 输入初始状态,求初始状态到最终状态的路径分别 用u(向上),d(向下),l(向左),r(向右)来表示四个方向的移动; 如果有解,则输出路径,否则输出"unsolvable" 有多个输入 */ #include #include #include #include using namespace std; long long f

liujan511536的专栏 1301

Calibre:LVS 快速debug short/open技巧

用Fix Suggestion和Short Isolate两种方法debug LVS问题

m0_61544122的博客 7462

POJ 1077 Eight (BFS+康托展开)详解

本题知识点和基本代码来自《算法竞赛 入门到进阶》(作者:罗勇军 郭卫斌) 如有问题欢迎巨巨们提出 题意:八数码问题是在一个3*3的棋盘上放置编号为1~8的方块,其中有一块为控制,与空格相邻的数字方块可以移动到空格里。我们要求指定初始棋盘和目标棋盘,计算出最少移动次数,同时要输出数码的移动数列。初始棋盘样例已给出,目标棋盘为“1 2 3 4 5 6 7 8 x” 输入: 2...

alnxtmp169007749的博客 243

模拟一个基站和一个移动台之间的信号传播

同样使用时间序列和上述参数计算出反射径信号的信号强度。根据时间序列和上述参数,计算出直射径信号的信号强度。该信号被视为一个简单的正弦波信号,其频率是2Hz。:时间序列,从0.1秒开始,每隔0.0001秒采样一次,直到12秒。:设置坐标轴范围,横轴范围为0到12秒,纵轴范围为-0.5到0.5。:移动台移动的速度。:移动台距离基站的初始距离。:基站到反射墙的距离。假设基站到反射墙的距离为15米。:绘制直射径信号、反射径信号和合成信号的波形图。:添加标签,标注每条曲线对应的含义。表示反射径信号的颜色为绿色,

Fanjufei的博客 292

【信息系统项目管理师】高分论文:论信息系统项目的整合管理(绩效考核系统)

我们将项目管理计划中的子计划包括项目范围、进度、成本、质量管理计划,过程改进计划,人力资源管理计划,风险、采购管理计划,干系人管理计划,项目范围、成本、进度基准作为依据,查看项目的各个方面,通过组织全体团体成员会议来解读由各监控过程提供的信息,之后我与项目管理团队一起制订所需措施,确保项目绩效达到预期要求。在一个项目中,变更是必然的,也是不可避免的,进度拖延,成本失控,客户有新的需求等都会引起项目的变更。在本项目中,我要求有处于工作状态的产品,开发人员才可以对其任意修改,修改完成后,重新入库即可。

数据知道的博客 6888

蓝桥杯 历届试题 九宫重排 (八数码问题--康托展开去重 + bfs搜索)

题意: 简单的八数码问题: 给你两个状态 求最少步数。 可以把点变成9: 这样,9个数都不一样,相当于是阶乘的排列。 直接用bfs 搜索 康托展开去重即可。 #include #include #include #include #include #include #include #include #define Siz(x) (int)x.size() #defi

aozil_yang的博客 1728

C++性能优化:深入理解缓存一致性与伪共享

在现代多核处理器的世界里,理解缓存一致性和伪共享就像理解一个复杂社会系统的运作规则。正如心理学家阿德勒所说:"人的行为总是有目的的",CPU缓存的每一次同步也都有其深层的硬件逻辑。本文将带你深入探索这些看不见的性能杀手,以及如何在实际项目中与它们优雅共处。

探索C++编程的奥秘,分享深入的技术见解和实践,旨在激发读者创造力与解决问题的思维。 936

POJ 1077 Eight (正向BFS + 康托展开)

题意不说了 八数码问题: 和上篇博客 HDU 1043  题目是一样的! 但是做法上有些出入。 HDU 时间限制比较长,而且是多组输入,所以要逆向bfs 进行打表处理。 而POJ 1077 这个题目,时间是1S ,单组输入。 因此输入一组 搜索一组即可。 9个数的排列  判重用康托展开来做。 但是这个队列要自己写,STL的queue 会超时。 自己写的队列,在输出时 能很方

aozil_yang的博客 859

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

8数码问题

8数码问题,即在一个3×3的矩阵中有8个数(1至8)和一个空格,从一个状态转换到另一个状态,每次只能移动与空格相邻的一个数字到空格当中 AOJ-417-8数码 http://icpc.ahu.edu.cn/OJ/Problem.aspx?id=417 这题是求转化的最少步数,可用BFS解决,共有9!=362880种情况,关键是如何标记已经访问过的状态,保证每次搜索得到的状态都是最小的步数,这...

java开发指南博客 【转载】 330

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

poj 1077 (康托展开+bfs)

这是一个八数码问题,正好学习了康托展开,就做了这题,和hdu1043很像。康托展开并不难理解,其实就是一种hash。先上模板方便以后自己看。康托展开:int Contor(int str[],int n) { int ans = 0; for(int i = 0; i &lt; n; i++) { int cnt = 0; for(int j...

Avalon_cc的博客 337

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

POJ 1077 Eight 八数码问题[康托展开 + BFS]

POJ 1077 Eight 八数码问题 [康托展开 + BFS] 题目链接:Here! 对于八数码问题,可能问题的关键不是BFS,而是对状态的标记。八数码的状态恰好是一个全排列,那么对于全排列,康托展开就是一个完美的哈希。 康托展开:X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! ,其中a[i]为当前未出现的元素中是排在第几个

Fighting! 1949

八数码 POJ1077 (康托展开与奇偶排列详解)

题目链接 八数码问题有多种解决方法,在这里只具体讲述一下康托展开在状态压缩中的应用。 题意: 输入一段数字序列,表示3×3棋盘0到8的一种排列状态,要求计算从初始状态到达目标状态(1 2 3 4 5 6 7 8 0)所需的最少步数,并输出操作过程。 思路: 本题的关键是标记每一种可能扩展到的状态,由于所有的状态个数对应的是9的全排列,如果仅仅是简单地扩展标记数组的维度必然会超内存,所以此时...

Keep eating codes! 849

poj 1077 八数码(BFS+康托展开)

1 /* 2 题意:八数码问题,给出3*3的矩阵含1~8以及x,给出一个符合的解使得移动后的矩阵的顺序为1~8,最后为x 3 4 题解:BFS 5 需要用到康托展开来表示状态,不然数组无法完全表示所有状态,这样BFS就无法判断找不到解的情况(status 6 的0ms,0KB究竟是怎么做到的,简直不能想象=。=) 7 */ 8 #inc...

dianxie7120的博客 328

【康托展开+状压BFS】poj1077 Eight(八数码问题)

The Cantor Expassion is something that help us to solve some problem about the numbers arrange. Besides, it can help to compress state(encode&decode), so that we can use BFS/DFS to solve those proble

When you go away 972

POJ1077八数码

POJ1077:八数码问题(Eight) POJ1077查看 文章目录POJ1077:八数码问题(Eight)@[toc]**解题思路**基础知识铺垫广度优先搜索BFS+康托展开广度优先搜索BFS+set二分查找双向广搜DBFS+set二分查找启发式算法+堆+普通标记数组更多策略 解题思路 求步数最少的解时候用广搜 状态的表示问题 若以字符串的形式表示,需要10字节,且检查是否达到目标状...

loveSiri的博客 1311

poj 1077--Eight(八数码问题,BFS+康托展开+路径打印)

题意:经典的八数码问题,题目已确定好目标状态,若从起始状态到目标状态有解,输出最短的到达路径的每一步操作;否则输出unsolvable。 思路:这是一道经典的八数码问题,采用BFS+康托展开判重,主要多了一步打印路径,把可变化位置x看成数字0放置位置,共有9个数字,即9!种状态,在数组可开的范围内,用pre结构体记录当前状态的前驱状态即转化过来的方式,再用栈倒过来打印答案即可。(BFS时用STL中...

weixin_44756457的博客 678

【POJ1077】Eight 八数码问题,解题报告+思路+代码

#include #include #include #define INPUT using namespace std; /** Problem : poj1077,hdu1043,经典的八数码问题。 知识点: BFS + HASH + 打表 + 父亲节点记录 境界:3 - BFS+HASH+打表 A了两天!!! 记得拿启发式,双向BFS重新写

c0de4fun的完美算(nei)法(he)教室-我们仍不知道,那天调用的驱动的名字。 5778

hdu 1043 /poj 1077 Eight(经典八数码问题,BFS+康托展开)

Eight Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 20170    Accepted Submission(s): 5371 Special Judge Problem Description The 1

TUT我好菜啊 774

poj 1077 八数码问题 + 康托展开 + bfs

新年第一题,拖了这么久才做掉。 //============================================================================ // // > File : poj1077.cpp // > Author : flowertree // > Time :

314

POJ 1077 八数码 三种解法

POJ 1077 Eight题目链接:http://poj.org/problem?id=1077

lvxin1204的博客 5398
上一篇: poj 1422 hungary算法(伞兵降落)
下一篇: poj 1423 stirling公式(阶乘的位数)
dumeichen
博客等级 码龄13年 55粉丝 475原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值