埃及分数 ——迭代加深搜
http://codevs.cn/problem/1288/
我写了三个版本的代码,第一个找到第一个答案就会退出,是错误的,
第二个是bool dfs版本的,第三个是void dfs版本的,其实都一样,不过bool 版本的容易判断结果是否找到,以前觉得bool版本很难理解,但是事实上void 版本return的地方对应看, 找到答案的return true ,继续找不可行 return false
这个代码看起来很讨厌,因为乍一看上去真的好多东西。。。
加数少好,相同情况下最后一个分数越大越好
1、实际上迭代加深搜框架:
2、get_first(a, b)是满足1/c≤a/b的最小c
3、答案要最小分数越大越好,每找到一个可行解 使用better()函数比较最后一个值
4、dfs(0, get_first(a, b), a, b) 其中第一个参数是深度,第二个参数是从哪个数开始减,a,b代表还需要凑的分数的分子和分母
每一次dfs找出该最大深度下的最优解,在该最大深度下找大解就停止加深深度。
//下面是我自己改的代码,A了,比上一个版本快了6ms
#include<iostream>
#include<cstring>
#include<stdio.h>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N=1000;
LL ans[N],now[N];
LL maxd;
int ko=0;
LL find_best(LL a,LL b)//寻找1/i<a/b i>b/a
{
return b/a+1;
}
LL gcd(LL a,LL b)
{
return b==0?a:gcd(b,a%b);
}
bool better(LL maxd)
{
return now[maxd]<ans[maxd]||ans[maxd]==-1;
}
void dfs(LL deep,LL frac,LL aa,LL bb) //该深度下跑完所有的量
{
bool ok;
if(deep==maxd)
{
if(bb%aa) return ; //aa!=1 该层查找失败 只到最后一层才开始确认是埃及分数吗??但是在递归的过程中每层的now[d]的修改都是经过检查的
now[deep]=bb/aa;
if(better(deep)) memcpy(ans,now,sizeof(LL)*(deep+1));
return ;
}
ok=false;
LL i=max(find_best(aa,bb),frac); //上一个传递下来的分母,要和现在要组成的数进行比较
for(i;;++i)
{
if((maxd+1-deep)*bb<=i*aa) break; //ok=false; return ok;
now[deep]=i;
//不剪枝的话就进行迭代,迭代的数为aa/bb-1/i;
LL b2=bb*i;
LL a2=aa*i-bb;
LL g=gcd(a2,b2);
dfs(deep+1,i+1,a2,b2); //如果下一深度找到最佳答案 就return ok 深度不够就一直递归增加深度! nice! 懂啦!
}
}
void solve(LL a,LL b)
{
int check=0;
for(maxd=1;;++maxd)
{
memset(ans,-1,sizeof(ans));
dfs(0,find_best(a,b),a,b);
if(ans[maxd]!=-1)
{
check=1;
break;
}
}
if(check)
{
for(int i=0;i<maxd;++i)
printf("%lld ",ans[i]);
printf("%lld\n",ans[maxd]);
}
}
int main()
{
LL a, b;
while(cin>>a>>b)
{
solve(a,b);
}
return 0;
}