EOJ1154 CAN YOU DFS? IDA*搜索算法

题目:EOJ1154 CAN YOU DFS?  IDA*搜索算法

Description

在古埃及,人们使用单位分数的和(形如1/a的, a是自然数)表示一切有理数。

如:2/3=1/2+1/6,但不允许2/3=1/3+1/3,因为加数中有相同的。

对于一个分数a/b,表示方法有很多种,但是哪种最好呢?

首先,加数少的比加数多的好,其次,加数个数相同的,最小的分数越大越好。

如:

19/45=1/3 + 1/12 + 1/180

19/45=1/3 + 1/15 + 1/45

19/45=1/3 + 1/18 + 1/30,

19/45=1/4 + 1/6 + 1/180

19/45=1/5 + 1/6 + 1/18.

最好的是最后一种,因为1/18比1/180,1/45,1/30,1/180都大。

给出a,b(0〈a〈b〈1000),编程计算最好的表达方式。

Input

每组测试数据为一行包含a,b(0〈a〈b〈1000)。

Output

每组测试数据若干个数,自小到大排列,依次是单位分数的分母。输出字典序最小的一组解。

Sample Input

19 45

Sample Output

5 6 18

题目分析:题意给出一个真分数,将它拆成若干个数分之一的形式。要求优先级如下:1,分数个数尽量少。2,最后一个分数的分母尽量大。3,分母字典序尽量小。

主要思路:按字典序搜索所有情况,若能够组合出所求分数,且最后一位分母更小,则更新答案。

这题主要难点是搜索边际的确定……一个数可以拆分成无数个数。又因为要求分数个数尽量少,所以可以每次限制搜索深度,逐渐增加搜索深度,知道找到答案。这就是迭代加深的搜索思想。

同时要求分母逐渐变大,即分数逐渐变小,若后面的分数均无限接近当前最后一个分数却任然无法在规定深度内搜索到正确答案时,就要进行剪枝,这就是A*算法的思想。

这题要综合上述两种思想。

归纳一下,IDA*的基本思路是:首先将初始状态结点的H值设为阈值maxH,然后进行深度优先搜索,搜索过程中忽略所有H值大于maxH的结点;如果没有找到解,则加大阈值maxH,再重复上述搜索,直到找到一个解。在保证H值的计算满足A*算法的要求下,可以证明找到的这个解一定是最优解

AC代码:

#include <iostream>

#include <cstdio>

#include <cstring>

using namespace std;

long long ans[1500],v[1500];

int maxd;

long long gcd(long long a,long longb){       //求gcd用于约分化简

return !b?a:gcd(b,a%b);

}

long long get_first(long long a,long long b){  //求拼b分之a时,第一个分数的最大值,分母最小值

long long c=b/a;

if(b%a) ++c;

return c;

}

bool dfs(long long a,long long b,long longfrom,int deep){

if(deep==maxd){   //达到规定最大搜索深度,结束当前搜索

if(a!=1)

return false;

v[deep]=b;

if(v[deep]<ans[deep] || ans[deep]==-1)          //判断是否更优解

memcpy(ans,v,sizeof(long long)*(deep+2));

return true;

}

bool ok=false;

for(int i=from;;++i){

if((maxd-deep+1)*b<=a*i) break;//无法在当前规定深度内找到解,剪枝,A*算法的思想

v[deep]=i;

long long aa=a*i-b,bb=b*i;

int c=gcd(aa,bb);

aa/=c;bb/=c;

from=max((long long)(i+1),get_first(aa,bb));//下次搜索的起点

if(dfs(aa,bb,from,deep+1)) ok=true;

}

return ok;

}

int main()

{

long long a,b;

while(~scanf("%I64d%I64d",&a,&b)){

long long c=gcd(a,b);

a/=c;b/=c;

for(maxd=1;;++maxd){            //逐渐增加递归深度,迭代加深

memset(ans,-1,sizeof(ans));

if(dfs(a,b,get_first(a,b),1)){

for(int i=1;i<=maxd;++i){

if(i>1) printf("");

printf("%I64d",ans[i]);

}

printf("\n");

break;

}

}

}

return 0;

}

时间: 2024-11-05 14:11:18

EOJ1154 CAN YOU DFS? IDA*搜索算法的相关文章

UVa 11212 编辑书稿(dfs+IDA*)

https://vjudge.net/problem/UVA-11212 题意:给出n个自然段组成的文章,将他们排列成1,2...,n.每次只能剪切一段连续的自然段,粘贴时按照顺序粘贴. 思路:状态空间的搜索问题. 首先介绍一下IDA*,它属于DFS,在DFS遍历的时候,设定一个深度上限maxd,当前结点n的深度为g(n),乐观估价函数为h(n),则当g(n)+h(n)>maxd时应           该剪枝.这样的算法就是IDA*. 在这道题目中,由于最多就9个数,所以最多只需要剪切8次肯定

UVa 1343 旋转游戏(dfs+IDA*)

https://vjudge.net/problem/UVA-1343 题意:如图所示,一共有8个1,8个2和8个3,如何以最少的移动来使得中间8个格子都为同一个数. 思路:状态空间搜索问题. 用IDA*算法的话会比较快,而且代码比较简洁. IDA*的关键就是要寻找一个估价函数h(),在这道题目中,每次移动最多只会使一个格子的数字正确,所以当maxd-d<h()时便可以剪枝. 1 #include<iostream> 2 #include<string> 3 #include

BFS/DFS算法介绍与实现(转)

广度优先搜索(Breadth-First-Search)和深度优先搜索(Deep-First-Search)是搜索策略中最经常用到的两种方法,特别常用于图的搜索.其中有很多的算法都用到了这两种思想,比如:Dijkstra单源最短路径算法和Prim最小生成树算法都采用了和宽度优先搜索类似的思想.BFS的思想:从一个图的某一个顶点V0出发,首先访问和V0相邻的且未被访问过的顶点V1.V2.--Vn,然后依次访问与V1.V2--Vn相邻且未被访问的顶点.如此继续,找到所要找的顶点或者遍历完整个图.由此

HDU - 3567 Eight II IDA*

Eight-puzzle, which is also called "Nine grids", comes from an old game. In this game, you are given a 3 by 3 board and 8 tiles. The tiles are numbered from 1 to 8 and each covers a grid. As you see, there is a blank grid which can be represente

DFS-leetcode Combination Sum I/I I

深度优先搜索(DFS)是搜索算法的一种.最早接触DFS应该是在二叉树的遍历里面,二叉树的先序.中序和后序遍历实际上都属于深度优先遍历,实质就是深度优先搜索,后来在图的深度优先遍历中则看到了更纯正的深度优先搜索算法. 通常,我们将回溯法和DFS等同看待,可以用一个等式表示它们的关系:回溯法=DFS+剪枝.所以回溯法是DFS的延伸,其目的在于通过剪枝使得在深度优先搜索过程中如果满足了回溯条件不必找到叶子节点,就截断这一条路径,从而加速DFS.实际上,即使没有剪枝,DFS在从下层回退到上层的时候也是一

编程算法

前十个是来自圣经的十大算法: 发起人的描述:<来自圣经的证明>收集了数十个简洁而优雅的数学证明,迅速赢得了大批数学爱好者的追捧.如果还有一本<来自圣经的算法>,哪些算法会列入其中呢? 第一名:Union-find 严格地说,并查集是一种数据结构,它专门用来处理集合的合并操作和查询操作.并查集巧妙地借用了树结构,使得编程复杂度降低到了令人难以置信的地步:用上 一些递归技巧后,各种操作几乎都能用两行代码搞定.而路径压缩的好主意,更是整个数据结构的画龙点睛之笔.并查集的效率极高,单次操作

图数据结构(期限、存储结构、遍历)

1.相关条款 顶点(Vertex).弧形(Arc).圆弧头(初始点).圆弧终点(端点).边缘(Edge).向图(Directed graph).无向图(Undigraph).完全图(Completed grapg).导演完全图.稀疏图(Sparse graph).密集图(Dense graph).权(weigh).网(network).无向网.有向网.子图(Subgraph).邻接点(Adjacent).度(Degree).入度(Indegree).出度(Outdegree).路径(path).

图的深度优先搜索算法DFS

1.问题描述与理解 深度优先搜索(Depth First Search,DFS)所遵循的策略,如同其名称所云,是在图中尽可能"更深"地进行搜索.在深度优先搜索中,对最新发现的顶点v若此顶点尚有未探索过从其出发的边就探索之.当v的所有边都被探索过,搜索"回溯"到从其出发发现顶点v的顶点.此过程继续直至发现所有从源点可达的顶点.若图中还有未发现的顶点,则以其中之一为新的源点重复搜索,直至所有的顶点都被发现.与BFS中源顶点是指定的稍有不同. DFS搜索轨迹Gπ将形成一片

深度优先搜索算法(DFS)以及leetCode的subsets II

深度优先搜索算法(depth first search),是一个典型的图论算法.所遵循的搜索策略是尽可能“深”地去搜索一个图. 算法思想是: 对于新发现的顶点v,如果它有以点v为起点的未探测的边,则沿此边继续探测下去.当顶点v的所有边都已被探寻结束,则回溯到到达点v的先辈节点.以相同方法一直回溯到源节点为止.如果图中还有未被发现的顶点,则选择其中一个作为源顶点,重复以上的过程.最后的结果是一些不相交的深度优先树. leetCode中的应用: Given a collection of integ