紫书搜索 习题7-7 UVA

来源:互联网 发布:迅捷数据恢复软件 编辑:程序博客网 时间:2024/04/26 13:24

题目链接:

https://vjudge.net/problem/UVA-12558

题意:

题解:

输出要用lld
IDA*迭代加深搜索
紫书例题改一改

代码:

#include <bits/stdc++.h>using namespace std;typedef long long ll;#define MS(a) memset(a,0,sizeof(a))#define MP make_pair#define PB push_backconst int INF = 0x3f3f3f3f;const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;inline ll read(){    ll x=0,f=1;char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}    return x*f;}//////////////////////////////////////////////////////////////////////////const int maxn = 10010;ll a,b,k,maxd;set<ll> ban;ll ans[maxn],v[maxn];ll gcd(ll x,ll y){    return y==0 ? x : gcd(y,x%y);}ll get_first(ll x,ll y){    if(y%x == 0) return y/x;    return y/x+1;}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;}bool dfs(int d,ll from,ll aa, ll bb){    if(d == maxd){        if(bb%aa) return false;        if(ban.count(bb/aa)) return false;        v[d] = bb/aa;        if(better(d)) memcpy(ans,v,sizeof(ll)*(d+1));        return true;    }    bool ok = false;    from = max(from,get_first(aa,bb)); // 因为aa/bb 越来越小, bb/aa 越来越大,所以每次枚举的起点是递增的,不会重复    for(ll i=from; ; i++){        if((maxd-d+1)*bb <= i*aa) break;        if(ban.count(i)) continue;        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; // 这里为什么不直接返回true了? 这一层要继续,会影响后面的值,当前层大了,后面就要有更小的分数出现,不是最优解        // i+1保证了不重复性    }    return ok;}int main(){    int T = read();    for(int cas=1; cas<=T; cas++){        ban.clear();        scanf("%I64d%I64d%I64d",&a,&b,&k);        for(int i=0; i<k; i++){            ll t = read();            ban.insert(t);        }        // cout << get_first(a,b) << endl;        for(maxd=1; ; maxd++){            memset(ans,-1,sizeof(ans));            if(dfs(0,get_first(a,b),a,b)) break;        }        printf("Case %d: %lld/%lld=",cas,a,b);        for(int i=0; i<maxd; i++)            printf("1/%lld+",ans[i]);        printf("1/%lld\n",ans[maxd]);    }    return 0;}
0 0
原创粉丝点击