1. 程式人生 > >Vijos 1308 埃及分數(叠代加深搜索)

Vijos 1308 埃及分數(叠代加深搜索)

better 方案 emc 分數 fine pri 深搜 can long long

題意:

輸入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];
bool better(int d){
    for(int i = d; i >= 0; i--){
        
if(v[i] != ans[i]){ //如果這一層沒有標記, 或者標記的數小於傳入的v[i], 說明當前為更優解 return ans[i] == -1 || v[i] < ans[i]; } return false; } } //求滿足 1/c <= a/b 最大的1/c, 即最小的c inline int get_first(LL a,LL b){ return b/a+1; } //當前深度為d, 分母不能小於from, 分數之和為aa, bb bool dfs(int d, int from, LL aa, LL bb){
if( d == maxd){ if(bb % aa) return false; v[d] = bb / aa; if(better(d)) memcpy(ans, v , sizeof(v)); return true; } bool ok = false; from = max(from, get_first(aa, bb)); // 如果上一次遞歸的from不符合aa/bb最小的分母, 則取get_first(aa,bb) for(int i = from; ; i++) { // 剪枝:如果剩下的maxd+1-d個分數全部都是1/i,加起來仍然不超過aa/bb,則無解
if(bb * (maxd+1-d) <= i * aa) break; v[d] = i; // 計算aa/bb - 1/i,設結果為a2/b2 LL b2 = bb*i; LL a2 = aa*i - bb; LL g = __gcd(a2, b2); // 以便約分 if(dfs(d+1, i+1, a2/g, b2/g)) ok = true; } return ok; } int main(){ int a, b; scanf("%d %d", &a, &b); for(maxd = 1; ;maxd++){ //這裏可以做一些限制, 層數上限不一定為infinite memset(ans, -1, sizeof(ans)); if(dfs(0,get_first(a,b),a,b)) { break; } } for(int i = 0; i <= maxd; i++) printf("%lld ", ans[i]); }

Vijos 1308 埃及分數(叠代加深搜索)