知识点:迭代搜索,剪枝

题意:

给定一个假分数\(\frac{a}{b}\),构造一系列数满足

\[\sum_{i=1}^n\frac{1}{a_i} \]

其中,每个\(a_i\)都是一个整数。所有解中,加数越少越优秀,相同加数数目,最小的加数越大越优秀,寻找最优秀的的解。

思路:

首先还是较为容易判断是搜素的,随即就来到一个边界问题。普通的搜索的话,不容易判定什么时候停止搜索。索性就提前限制搜索深度,实际上就变成了一个迭代搜索。新的体悟是,这种方法有点像二分答案,没有直达答案的方法,就一个个枚举,判断是否符合可能为答案。二分通过单调性节约时间搜索通过剪枝

剪枝主要是两点,每次匹配\(\frac{1}{a_i}\)和当前需要匹配数\(\frac{a}{b}\)都需要

\[\frac{1}{a_i}<\frac{a}{b} \]

\[\frac{1}{a_i}*(limit-depth)>=\frac{a}{b} \]

三式子中,limit为限制深度,depth为当前深度。

额外一些次要的剪枝见代码

题解:

#include<cstdio>
#include<iostream>
#include<cmath>
#include<vector>
#include<string>
#include<cstring>
#include<algorithm>
#define rep(i,l,n) for(int i=(l);i<=(n);++i)
#define ll long long
using namespace std;
ll gcd(ll a,ll b)
{
    return b?gcd(b,a%b):a;
}
int fz,fm;
ll ans[1000],ans_len,tepans[1000],tepans_len;
void dfs(int cs,ll fz,ll fm,int limit)
{
    if(cs>limit)return; //超过limit返回
    if(fm%fz==0&&fm/fz>tepans[tepans_len]&&(ans_len==0||fm/fz<ans[ans_len]))
    {
        ++tepans_len;
        tepans[tepans_len]=fm/fz;
        ans_len=tepans_len;
        memcpy(ans,tepans,sizeof(ans));
        --tepans_len;
        return;
        // 这是到达终点,记录答案返回,第一次到达终点不一定是最优答案。
    }
    ll i=fm/fz;
    if(i<=tepans[tepans_len])i=tepans[tepans_len]+1;
    //i的取值,满足式子2,3,同时也应当优于上次的最优解tepans
    ll j=(limit-cs)*fm/fz;
    while(i<=j)
    {
        if(ans_len>0&&i>=ans[ans_len])return;
        int k=gcd(fm,i);
        ll xfm=i*fm/k,xfz=fz*i/k-fm/k;
        if(xfz<=0)
        {
            ++i;
            continue;
        }
        tepans[++tepans_len]=i;
        dfs(cs+1,xfz,xfm,limit);
        tepans_len--;
        ++i;
    }
    return ;
}
int main()
{
    while(scanf("%d%d",&fz,&fm)!=EOF)
    {
        memset(ans,0,sizeof(ans));
        memset(tepans,0,sizeof(tepans));
        ans_len=0,tepans_len=0;
        int limit=1;
        while(limit)
        {
            dfs(1,fz,fm,limit);
            if(ans_len)break;
            ++limit;
        }
        rep(i,1,ans_len)
        {
            if(i!=1)printf(" ");
            printf("%lld",ans[i]);
        }
        printf("\n");
    }
//    system("pause");
    return 0;
}
 posted on 2022-09-19 22:40  8号选手  阅读(48)  评论(0)    收藏  举报