[codevs1288]埃及分數 迭代加深搜索

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

數據範圍及提示 Data Size & Hint
學習了個迭代加深
#include<bits/stdc++.h>
using namespace std;
const int N = 5000 + 5;
typedef long long ll;
ll gcd( ll a, ll b ){ return b == 0 ? a : gcd( b, a%b ); }
void yue( ll &a, ll &b ){
	ll t = gcd( a, b );
	a /= t; b /= t;
}
ll a,b,ans[N],as[N]; int tot; bool flag=0;
void dfs( ll a, ll b, int step, int pre ){
	yue( a, b );
	if( step == 1 ){
		if( a == 1 && b > pre ){
			if( flag && b >= ans[1] ) return;
			flag = 1; as[1] = b;
			memcpy( ans, as, sizeof(as) );
		}
		return;
	}
	for( int i = pre, mx = ceil((double)b*step/a); i <= mx; i++ )
		as[step] = i, dfs( a * i - b, b * i, step - 1, i );
}
int main(){
	scanf("%lld%lld", &a, &b);
	yue( a, b );
	while( !flag ) dfs( a, b, ++tot, 1 );
	for( int i = tot; i; i-- ) printf("%lld ", ans[i]);
	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章