1. 程式人生 > >埃及數字(叠代深搜)

埃及數字(叠代深搜)

使用 tmp small 一個點 des 描述 相同 max amp

題目描述 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

一個叠代加深模版題,然而我默默地打了一個晚上。。

主要註意剪枝和數據要開longlong,因為沒開longlong在codves上最後一個點爆了

#include<bits/stdc++.h>
#define ll long long
using
namespace std; ll a,b,maxd,ans[1010],tmp[1010]; ll gcd(ll x,ll y){ return y?gcd(y,x%y):x; } bool dfs(ll a,ll b,ll step){ if(step==maxd){ if(a==1){ if(b>tmp[step-1]){ tmp[step]=b; if(tmp[step]<ans[step]){ for(int i=1
;i<=step;i++) ans[i]=tmp[i]; } } return 1; } else return 0; } if(a/(b*(maxd-step+1))>ans[maxd]) return 0; bool ok=0; for(int i=max(tmp[step-1]+1,b/a);i<=b*(maxd-step+1)/a;i++){ if(b>a*i) continue; tmp[step]=i; ll c=gcd(a*i-b,b*i); if(dfs((a*i-b)/c,(b*i)/c,step+1)) ok=1; } if(!ok)return 0;return 1; } int main(){ scanf("%lld%lld",&a,&b); ll c=gcd(a,b); a/=c;b/=c; if(a==1){ printf("%lld",b); return 0; } for(int i=1;i<=1000;i++) ans[i]=10000000; for(maxd=2;;maxd++){ memset(tmp,0,sizeof(tmp));tmp[0]=1; if(dfs(a,b,1)){ for(int i=1;i<=maxd;i++) printf("%d ",ans[i]);return 0; } } }

埃及數字(叠代深搜)