埃及分数

11 篇文章 0 订阅

题目描述 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/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大于1小于1000编程计算最好的表达方式。
输入描述 Input Description
a b

输出描述 Output Description
若干个数,自小到大排列,依次是单位分数的分母。

样例输入 Sample Input
19 45

样例输出 Sample Output
5 6 18

这里用到的是迭代加深搜索
援引一下http://blog.csdn.net/acdreamers/article/details/18226915
迭代加深搜索,实质上是限定下界的深度优先搜索。即首先允许深度优先搜索K层,若没有发现可行解,再将K+1后

重复以上步骤搜索,直到搜索到可行解。

在迭代加深搜索的算法中,连续的深度优先搜索被引入,每一个深度约束逐次加1,直到搜索到目标为止。这样可以

看出重复搜索了好多。但是它的好处在于:

1.空间开销小 每个深度下实际上是一个深度优先搜索,不过深度有限制,而DFS的空间消耗小是众所周知的。
2.利于深度剪枝
3.时间效率不低 虽然重复搜索,但是大家不难理解,前一次搜索跟后一次相不是微不足到的。

我们可以看出,迭代加深搜索算法就是仿广度优先搜索的深度优先搜索。既能满足深度优先搜索的线性存储要求,又能保证发现一个最小深度的目标结点。

从实际应用来看,迭代加深搜索的效果比较好,并不比广度优先搜索慢很多,但是空间复杂度却与深度优先搜索相同,比广度优先搜索小很多。

使用搜索算法的时候,选择正确的搜索方式很重要。当有一类问题需要做广度优先搜索,但却没有足够的空间,而时间却很充裕,碰到这类问题,我们可以选择迭代加深搜索算法。

个人:

#include <iostream>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXDEPTH=10,maxlongint=2147483647;//我们暂定最大的深度是10个分数。
int depth;
bool found;
int answer[MAXDEPTH],d[MAXDEPTH];
int gcd(int n,int m)
{
    int t=n%m;
    while(t)
    {
        n=m;
        m=t;
        t=n%m;
    }
    return m;
}
void slove(int a,int b,int k)
{
    int i,m,s,t;
    if(k==depth+1)//超过预定深度,就是终点了。
        return;
    else if(b%a==0&&b/a>d[k-1])//为了便于比较和题目要求,我们假定分母b1,b2,……bn依次递增。
    {
        d[k]=b/a;
        if(!found||d[k]<answer[k])
        memcpy(answer,d,sizeof(d));
        found=true;
        return;
    }
    //确定上下限。
    s=max(d[k-1],b/a)+1;//一样的要比前一个分母大同时小于枚举的分数总和
    t=(depth-k+1)*b/a;
    t=min(t,maxlongint/b);
    if(found)t=min(t,answer[depth-1]);//最后一个分数越大越好
    for(int i=s;i<=t;i++)
    {
        d[k]=i;
        m=gcd(a*i-b,b*i);//把这1/i从还要枚举的分数和中减去,a/b-1/i=(a*i-b)/(b*i);
        slove((i*a-b)/m,b*i/m,k+1);//取最约分数。
    }
}
int main()
{
  found=false;
  d[0]=1;
  int a,b;
  cin>>a>>b;
  for(depth=1;depth<=MAXDEPTH;depth++)
  {
      slove(a,b,1);
      if(found)
      {
          for(int i=1;i<=depth;i++)
              cout<<answer[i]<<" ";
          cout<<endl;
          break;
      }
  }
return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值