• 【Uva 12558】 Egyptian Fractions (HARD version) (迭代加深搜,IDA*)


    IDA* 就是iterative deepening(迭代深搜)+A*(启发式搜索)

    启发式搜索就是设计估价函数进行的搜索(可以减很多枝哦~)

    这题。。。

    理论上可以回溯,但是解答树非常恐怖,深度没有明显上界,加数的选择理论上也是无限的。

    我们可以从小到大枚举深度maxd,

    设计估价函数,当扩展到第i层,前i个分数的和为c/d,第i的分数为1/e,接下来至少需要(a/b+c/d)/(1/e)个分数,如果超过maxd-i+1,那么直接回溯就好了。。

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<iostream>
     5 #include<algorithm>
     6 #include<queue>
     7 #include<cmath>
     8 using namespace std;
     9 #define LL long long
    10 #define Maxn 1100
    11 
    12 LL a,b;
    13 LL maxd,ans[Maxn],v[Maxn];
    14 
    15 bool qq[1010];
    16 
    17 LL mymax(LL x,LL y) {return x>y?x:y;}
    18 
    19 bool better(LL d)
    20 {
    21     for(LL i=d;i>=1;i--) if(v[i]!=ans[i])
    22     {
    23         return ans[i]==-1||v[i]<ans[i];
    24     }
    25     return 0;
    26 }
    27 
    28 LL get_first(LL a,LL b)
    29 {
    30     for(LL i=1;;i++)
    31     {
    32         if(b<=a*i) return i;
    33     }
    34 }
    35 
    36 LL gcd(LL a,LL b)
    37 {
    38     if(b==0) return a;
    39     return gcd(b,a%b);
    40 }
    41 
    42 bool dfs(LL d,LL from,LL aa,LL bb)
    43 {
    44     if(d==maxd)
    45     {
    46         if(bb%aa) return 0;
    47         v[d]=bb/aa;
    48         if(v[d]<=1000&&!qq[v[d]]) return 0;
    49         if(better(d)) memcpy(ans,v,sizeof(ans));
    50         return 1;
    51     }
    52     bool ok=0;
    53     from=mymax(from,get_first(aa,bb));
    54     for(LL i=from;;i++) 
    55     {
    56         if(i<=1000&&!qq[i]) continue;
    57         if(bb*(maxd+1-d)<=i*aa) break;
    58         v[d]=i;
    59         LL b2=bb*i;
    60         LL a2=aa*i-bb;
    61         LL g=gcd(a2,b2);
    62         if(dfs(d+1,i+1,a2/g,b2/g)) ok=1;
    63     }
    64     return ok;
    65 }
    66 
    67 int main()
    68 {
    69     LL T,kase=0;
    70     scanf("%lld",&T);
    71     while(T--)
    72     {
    73         scanf("%lld%lld",&a,&b);
    74         memset(qq,1,sizeof(qq));
    75         LL k;
    76         scanf("%lld",&k);
    77         for(LL i=1;i<=k;i++)
    78         {
    79             LL x;
    80             scanf("%lld",&x);
    81             qq[x]=0;
    82         }
    83         for(maxd=1;;maxd++)
    84         {
    85             memset(ans,-1,sizeof(ans));
    86             if(dfs(1,get_first(a,b),a,b)) break;
    87         }
    88         printf("Case %lld: %lld/%lld=",++kase,a,b);
    89         printf("1/%lld",ans[1]);
    90         for(LL i=2;i<=maxd;i++) printf("+1/%lld",ans[i]);
    91         printf("
    ");
    92         /*printf("%d
    ",maxd);
    93         for(LL i=1;i<=maxd;i++) printf("%d
    ",ans[i]);*/
    94     }
    95     return 0;
    96 }
    View Code

    话说题目上的hard case我的程序也跑不出来。。。ORZ。。

    2016-11-14 20:17:33

  • 相关阅读:
    JS-Date日期内置对象
    JS-string内置对象
    MyBatis的事务处理
    MyBatis的简单操作
    MyBatis第一个项目示例
    CSS-盒子模型
    百分比布局的使用
    使用TabLayout快速实现一个导航栏
    彻底理解android中的内部存储与外部存储
    Eclipse的LogCat总是自动清空怎么办?
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/6063256.html
Copyright © 2020-2023  润新知