IDA*算法,迭代加深搜索和A*算法的结合 。
迭代加深搜索适用于那些没有明显深度上限的题目,将深度从小到大枚举,直到找到最优解 ,减小了深搜的盲目性 。
A*算法需要一个乐观估价函数,在这个函数里寻找一个代价最小的点去搜索,所以时间复杂度都浪费在这个上面了 。
代码如下:
#include<bits/stdc++.h> using namespace std; typedef long long ll; int T,kase=0; ll v[10000+10],ans[10000+10],a,b,e,k,maxd; set<ll> g; bool better(int d) { for(int i=d;i>=0;i--) if(v[i] != ans[i]) { return ans[i] == -1 || v[i] < ans[i]; } return false; } ll get_first(ll a,ll b) { return b/a + 1; } ll gcd(ll a,ll b) { return b == 0 ? a : gcd(b, a%b); } bool dfs(int d,ll from,ll aa, ll bb) { if(d == maxd) { if(bb % aa) return false; v[d] = bb/aa; if(g.count(bb/aa)) return false; //判断最后一个分数是不是可以出现 if(better(d)) memcpy(ans,v,sizeof(ll) * (d+1)); return true; } bool ok = false; from = max(from,get_first(aa,bb)); for(ll i = from; ; i++) { if(g.count(i)) continue;//判断每一个分数是不是可以出现 if(bb * (maxd+1-d) <= i * aa) break; //用乐观估计来剪枝 v[d] = i; 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() { scanf("%d",&T); while(T--) { scanf("%lld%lld%lld",&a,&b,&k); g.clear(); for(int i=0;i<k;i++) { scanf("%lld",&e); g.insert(e); } for(maxd = 1; ; maxd++) { memset(ans,-1,sizeof(ans)); if(dfs(0,get_first(a,b),a,b)) break; } printf("Case %d: %lld/%lld=1/%lld",++kase,a,b,ans[0]); for(int i=1;i<=maxd;i++) printf("+1/%lld",ans[i]); printf("\n"); } return 0; }