1. 程式人生 > >UVA12558 Egyptian Fractions (HARD version) (埃及分數)

UVA12558 Egyptian Fractions (HARD version) (埃及分數)

include 範圍 sin ring ble gyp lld ret ++i

UVA12558 Egyptian Fractions (HARD version)

題解

叠代加深搜索,適用於無上界的搜索。每次在一個限定範圍中搜索,如果無解再進一步擴大查找範圍。

本題中沒有分數個數和分母的上限,只用爆搜絕對TLE。故只能用叠代加深搜索。

#include<cstdio>
#include<cstring>
#include<set>
using namespace std;
typedef long long ll;
int num,T,t,k;
ll h[100001],ans[100001],a,b,q;
set <ll> del; //存儲不能用的數
bool ok; inline ll gcd(ll A,ll B) {return B ? gcd(B,A%B):A;} inline bool better(){ //判斷最優解 for(int i=num;i>=0;--i) if(h[i]!=ans[i]) return ans[i]==-1||h[i]<ans[i]; return 0; } inline void dfs(ll p1,ll p2,int last,int cnt){//p1/p2:分子/分母 last:這次從哪個分母開始搜 cnt:已經添加了幾個子分數 if(cnt==num){
if(p2%p1||del.count(p2/p1)) return ; //分子不為1或者這個數被禁止出現 h[cnt]=p2; ok=1; if(better()) memcpy(ans,h,sizeof(ll)*(cnt+1)); //更新最優解 return ; } for(ll i= last>p2/p1+1 ? last:p2/p1+1;;++i) // p2/p1+1:符合條件的最小分母,用於剪枝 { if(p1*i>=p2*(num-cnt+1)) break; //發現最後減不完了,跳出
if(del.count(i)) continue; ll q1=p1*i-p2,q2=p2*i,G=gcd(q1,q2); //通分 h[cnt]=i; dfs(q1/G,q2/G,i+1,cnt+1); } } int main(){ scanf("%d",&T); for(t=1;t<=T;++t){ del.clear(); ok=0; scanf("%lld%lld%d",&a,&b,&k); for(int i=1;i<=k;++i) scanf("%lld",&q),del.insert(q); for(num=1;!ok;++num){ memset(ans,-1,sizeof(ans)); dfs(a,b,b/a+1,0); //b/a+1同上p2/p1+1 }--num; //註意要減掉多出的一次++num操作 printf("Case %d: %lld/%lld=",t,a,b); for(int i=0;i<num;++i) printf("1/%lld+",ans[i]); printf("1/%lld\n",ans[num]); } return 0; }

UVA12558 Egyptian Fractions (HARD version) (埃及分數)