DFSID:埃及分数

题目描述 

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 Description

a b

输出描述 Output Description

若干个数,自小到大排列,依次是单位分数的分母。

样例输入 Sample Input

19 45

样例输出 

Sample Output

5 6 18

思路:
对于此种题,枚举没有限制,不能用广搜,考虑使用迭代加深搜。
迭代加深搜:迭代加深搜索,实质上就是限定下界的深度优先搜索。即首先允许深度优先搜索K层搜索树,          若没有发现可行解,再将K+1后重复以上步骤搜索,直到搜索到可行解。

对于这道题,依次搜索第一层,第二层,第三层,....,第k层判断上下界:上界: (x*b) div a          下界: b div a下界理由:搜索的分数一定小于等于当前的分数上界理由:如果接下来所有的分数都相等,那么(x*b) div a

如果第k层得到解,停止搜索,输出,否侧继续搜索

判断当前的解优于暂存的解,那么if (temp[0]=init[0])and(init[init[0]]>temp[temp[0]] swap(temp,init);                          if init[0]>temp[0] swap(init,temp);

code:
var i:longint;    j,k:longint;    m,init:array[0..1000]of longint;    a,b:longint;
function min(x,y:longint):longint;         begin if x>y                  then exit(y)                  else exit(x);         end;
function max(x,y:longint):longint;         begin if x>y                  then exit(x)                  else exit(y);         end;
function gcd(x,y:longint):longint;         begin if y=0                  then exit(x)                  else exit(gcd(y,x mod y));         end;
function can(x:longint):boolean;         var i:longint;             aa,bb,temp:longint;
         procedure dfs(deep,a,b:longint);                   var i:longint;                       aa,bb:longint;                       j,k:longint;                   begin if (deep>x)and(a=0)                            then begin if (m[0]=init[0])and(init[init[0]]<m[m[0]])                                          then begin for i:=0 to init[0] do                                                         m[i]:=init[i];                                               end;                                       if (m[0]>init[0])                                          then begin for i:=0 to init[0] do                                                         m[i]:=init[i];                                               end;                                 end;                         if (deep>x)                            then exit;                         if a<=0                            then exit;                         j:=max(b div a,init[deep-1]+1);                         k:=((x-deep+1)*b) div a+1;                         for i:=j to k do                             begin inc(init[0]);                                   init[init[0]]:=i;                                   temp:=gcd(b,i);                                   bb:=max(b,i) div temp *min(b,i);                                   aa:=a*(i div temp)-(b div temp);                                   dfs(deep+1,aa,bb);                                   dec(init[0]);                             end                   end;
         begin if x=1                  then begin i:=1;                             while (a/b<1/i) do inc(i);                             if a/b=1/i                                then begin m[0]:=1;                                           m[1]:=i;                                           exit(true);                                     end                                else begin exit(false);                                     end;                       end;               m[0]:=maxlongint;               fillchar(init,sizeof(Init),0);               if x<>1                  then begin j:=(b div a);                             k:=(x*b) div a+1;                             for i:=j to k do                                 begin init[0]:=1;                                       init[1]:=i;                                       temp:=gcd(b,i);                                       bb:=max(b,i) div temp *min(b,i);                                       aa:=a*(i div temp)-(b div temp);                                       dfs(2,aa,bb);                                       dec(init[0]);                                 end;                             if m[0]=maxlongint                                then exit(false)                                else exit(true);                       end;         end;
begin      readln(a,b);      i:=3;      while not can(i) do            inc(i);      for i:=1 to m[0] do          write(m[i],‘ ‘);end.
时间: 2024-10-19 09:01:37

DFSID:埃及分数的相关文章

1288 埃及分数

1288 埃及分数 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 查看运行结果 题目描述 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/

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

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

将真数分解为埃及分数

问题: 输入一个分数,将该分数分解为埃及分数. 真分数:分子小于分母的分数 埃及分数:分子为一的分数 #include <stdio.h> #include <stdlib.h> /* run this program using the console pauser or add your own getch, system("pause") or input loop */ int main(int argc, char *argv[]) { long in

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

一.题目背景 http://codevs.cn/problem/1288/ 给出一个真分数,求用最少的1/a形式的分数表示出这个真分数,在数量相同的情况下保证最小的分数最大,且每个分数不同. 如 19/45=1/3 + 1/12 + 1/180 二.迭代加深搜索 迭代加深搜索可以看做带深度限制的DFS. 首先设置一个搜索深度,然后进行DFS,当目前深度达到限制深度后验证当前方案的合理性,更新答案. 不断调整搜索深度,直到找到最优解. 三.埃及分数具体实现 我们用dep限制搜索层数,先从2开始,每

埃及分数,迭代加深

埃及分数题意非常明白,这里就不解释了…… 但是关于最优解的问题,题目并没有说明 原题: 对于一个分数a/b,表示方法有很多种,但是哪种最好呢? 首先,加数少的比加数多的好,其次,加数个数相同的,最小的分数越大越好. 然而这并没有考虑一种很恶心的情况:加数一样多,而且最后一个分数一样的时候,哪种情况最优呢? 我先写了个从末尾到开头一位一位判断大小,保证最大的程序,大概只有一半的分数(codevs) 又写了个输出 最先找到的 末尾最大的 方案 的程序,结果90(还是codevs) 我选择放弃,,,

将真分数分解为埃及分数

描述 分子为1的分数称为埃及分数.现输入一个真分数(分子比分母小的分数,叫做真分数),请将该分数分解为埃及分数.如:8/11 = 1/2+1/5+1/55+1/110. 接口说明 /* 功能: 将分数分解为埃及分数序列 输入参数:     String pcRealFraction:真分数(格式“8/11”) 返回值:     String pcEgpytFraction:分解后的埃及分数序列(格式“1/2+1/5+1/55+1/100”) */ public static String  Co

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

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

迭代加深,埃及分数

问题描述: 给出一个分数,由分子a 和分母b 构成,现在要你分解成一系列互不相同的单位分数(形如:1/a,即分子为1),要求:分解成的单位分数数量越少越好,如果数量一样,最小的那个单位分数越大越好. 如: 19/45 = 1/3 + 1/12 + 1/180; 19/45 = 1/5 + 1/6 + 1/18; 由于,1/18比1/180更大,所以第二种情况更优. 59/211=1/4 + 1/36 + 1/633 + 1/3798 59/211=1/6 + 1/9 + 1/633 + 1/37

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

题意: 输入a.b, 求a/b 可以由多少个埃及分数组成. 埃及分数是形如1/a , a是自然数的分数. 如2/3 = 1/2 + 1/6, 但埃及分数中不允许有相同的 ,如不可以2/3 = 1/3 + 1/3. 求出可以表达a/b个数最少埃及分数方案, 如果个数相同则选取最小的分数最大. #include <bits/stdc++.h> #define LL long long using namespace std; int maxd; long long v[1234],ans[1234

埃及分数&amp;&amp;The Rotation Game&amp;&amp;骑士精神——IDA*

IDA*:非常好用的搜索,可以解决很多深度浅,但是规模大的搜索问题. 估价函数设计思路:观察一步最多能向答案靠近多少. 埃及分数 题目大意: 给出一个分数,由分子a 和分母b 构成,现在要你分解成一系列互不相同的单位分数(形如:1/a,即分子为1),要求:分解成的单位分数数量越少越好,如果数量一样,最小的那个单位分数越大越好. 如: 19/45 = 1/3 + 1/12 + 1/180; 19/45 = 1/5 + 1/6 + 1/18; 以上两种分解方法都要3个单位分数,但下面一个的最小单位分