埃及分数问题_迭代加深搜索_C++

一、题目背景

  http://codevs.cn/problem/1288/

  给出一个真分数,求用最少的1/a形式的分数表示出这个真分数,在数量相同的情况下保证最小的分数最大,且每个分数不同。

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

二、迭代加深搜索

  迭代加深搜索可以看做带深度限制的DFS。

  首先设置一个搜索深度,然后进行DFS,当目前深度达到限制深度后验证当前方案的合理性,更新答案。

  不断调整搜索深度,直到找到最优解。

三、埃及分数具体实现

  我们用dep限制搜索层数,先从2开始,每次深度+1

  搜索时每一层比上一层的分数小,即分母一次比一次大

  每次枚举出 1/a 后,用当前分数减去,然后递归传递剩余的分数

  每层搜索枚举的限制条件:

    1、保证当前深度分母大于上一深度分母

    2、枚举的1/a小于当前分数,不可能存在等于的状态,因为此种最优解会在限制深度较小的时候出现

    3、设当前剩余分数为x/y,剩余深度为d,则 x/y<d/a → a<d/x*y。

       不妨先设之后枚举的分母都为 a,那么最后也就刚好达到 x/y ,但又因分数不能相等,所以 a 必须小于该值,即把分数调大。如果分数很小,那么就永远够不着目标分数

  当深度达到限制深度时,只需判断剩余的分数是否满足1/a的形式,然后更新结果

  记得开long long ,使用%lld输出,因为通分的时候数据会很大

  时间复杂度和搜索大致一致,因为当前限制深度的时间复杂度远大于上一次限制深度的时间复杂度,所以之前深度的时间可以忽略

  优点是空间开支特别小

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<iostream>
 6 #include<algorithm>
 7 #define N 1000
 8 using namespace std;
 9
10 long long ans[N],s[N],mo,ch;
11 int dep;
12 long long gcd(long long a,long long b){return b==0?a:gcd(b,a%b);}
13 void outp()
14 {
15     int i;
16     if (ans[dep]>s[dep])
17         {
18             for (i=1;i<=dep;i++)
19             {
20                 ans[i]=s[i];
21             }
22         }
23 }
24 void dfs(long long x,long long y,int d)
25 {
26     long long a,b,i,w;
27     if (d==dep)
28     {
29         s[d]=y;
30         if ((x==1)&&(s[d]>s[d-1])) outp();
31         return;
32     }
33     for (i=max(s[d-1]+1,y/x+1);i<(dep-d+1)*y/x;i++)
34     {
35         b=y*i/gcd(y,i);
36         a=b/y*x-b/i;
37         w=gcd(a,b);
38         a/=w;
39         b/=w;
40         s[d]=i;
41         dfs(a,b,d+1);
42     }
43 }
44 int main()
45 {
46     int i=0,j;
47     scanf("%d%d",&ch,&mo);
48     i=gcd(ch,mo);
49     ch/=i;
50     mo/=i;
51     for (dep=2;;dep++)
52     {
53         ans[1]=0;
54         s[0]=0;
55         ans[dep]=2000000000;
56         dfs(ch,mo,1);
57         if (ans[1]!=0) break;
58     }
60     for (j=1;j<=dep;j++)
61     {
62         printf("%lld ",ans[j]);
63     }
64     printf("\n");
65     return 0;
66 }

版权所有,转载请联系作者,违者必究

QQ:740929894

时间: 2024-08-09 07:22:53

埃及分数问题_迭代加深搜索_C++的相关文章

【迭代加深搜索】埃及分数问题

谢谢阿苏~http://blog.csdn.net/urecvbnkuhbh_54245df/article/details/5856756 [迭代加深搜索(ID,iterative deepening)]:从小到大枚举上限maxd,每次执行只考虑深度不超过maxd的结点. ------对于可以用回溯法求解但解答树的深度没有明显上限的题目,可以考虑ID算法: ------优点:它主要是在递归搜索函数的开头判断当前搜索的深度是否大于预定义的最大搜索深度,如果大于,就退出这一层的搜索,如果不大于,就

vijos1308 埃及分数(迭代加深搜索)

题目链接:点击打开链接 题目描述: 在古埃及,人们使用单位分数的和(形如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

“埃及分数”问题浅谈对迭代加深搜索的理解

迭代加深搜索(IDDFS)的思想 迭代加深搜索一般用来求解状态树"非常深",甚至深度可能趋于无穷,但是"目标状态浅"的问题.如果用普通的DFS去求解,往往效率不够高.此时我们可以对DFS进行一些改进.最直观的一种办法是增加一个搜索的最大深度限制maxd,一般是从1开始.每次搜索都要在maxd深度之内进行,如果没有找到解,就继续增大maxd,直到成功找到解,然后break. 如下图所示,如果用DFS,需要15步才能找到结点3,但是用迭代加深搜索,很快即可找到结点3.

搜索专题小结:迭代加深搜索

迭代加深搜索 迭代加深搜索(Iterative Deepening Depth-First Search, IDDFS)经常用于理论上解答树深度上没有上界的问题,这类问题通常要求出满足某些条件时的解即可.比如在"埃及分数"问题中要求将一个分数a/b分解成为若干个形如1/d的加数之和,而且加数越少越好,如果加数个数相同,那么最小的分数越大越好.下面总结一下该方法的一般流程: (1)概述:迭代加深搜索是通过限制每次dfs的最大深度进行的搜索.令maxd表示最大的搜索深度,那么dfs就只能在

UVA-11214 Guarding the Chessboard (迭代加深搜索)

题目大意:在一个国际象棋盘上放置皇后,使得目标全部被占领,求最少的皇后个数. 题目分析:迭代加深搜索,否则超时. 小技巧:用vis[0][r].vis[1][c].vis[2][r+c].vis[c-r+N]分别标志(r,c)位置相对应的行.列.主.副对角线有没有被占领(详见<入门经典(第2版)>P193),其中N表示任意一个比行数和列数都大(大于等于)的数. 代码如下: # include<iostream> # include<cstdio> # include&l

USACO/fence8 迭代加深搜索+剪枝

题目链接 迭代加深搜索思想. 枚举答案K,考虑到能否切出K个木头,那么我们当然选最小的K个来切. 1.对于原材料,我们是首选最大的还是最小的?显然,首选大的能够更容易切出,也更容易得到答案. 2.对于目标木头,我们是优先得到最大的还是最小的?显然,由于K个木头我们都要得到,那么当然先把最大的(最难得到的)先得到,这种搜索策略更优. 3.假设总原材料为all,前K个木头总和为sum,那么all-sum就是这一次切割过程中能[浪费]的最大数目.对于一个切剩下的原材料,若它比最小的目标木头还要小,则它

hdu 1560 DNA sequence(迭代加深搜索)

DNA sequence Time Limit : 15000/5000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other) Total Submission(s) : 15   Accepted Submission(s) : 7 Font: Times New Roman | Verdana | Georgia Font Size: ← → Problem Description The twenty-first century

hdu 1560 迭代加深搜索

链接:http://acm.hdu.edu.cn/showproblem.php?pid=1560 只能说bin神太给力了.. 又学到不少新知识.. 迭代加深搜索,貌似 又叫IDA*, 就是给搜索深度一个限制,搜索到一个满足条件就结束. 注意剪枝~ 代码: #include <iostream> #include <cstdio> #include <cstring> using namespace std; char g[10][10]; int size[10];

【wikioi】2495 水叮当的舞步(A*+迭代加深搜索)

这题我还是看题解啊囧.(搜索实在太弱.完全没想到A*,还有看题的时候想错了,.,- -) 好吧,估价还是那么的简单,判断颜色不同的数目即可(左上角的联通块不算在内) 然后A*还是一样的做法. 迭代加深还是一样的味道- 在这里我们用c[i][j]来表示左上角开始的联通块和联通块外面一层(因为要从外面一层拓展颜色),分别记为1和2 那么我们在搜索的时候,染色只要染c[i][j]为2的颜色种类,并且更新联通块(在这里不需要传图,因为一层一层的拓展下去的话,是单调递增的,所以用不到之前的颜色)我们在搜索