• 【算法学习笔记】17.暴力求解法05 隐式图搜索1 迭代加深搜索 埃及分数


    题目

    http://codevs.cn/problem/1288/

    卧槽。整了一天还是没全 AC 后面多层的时候不知道问题出在哪里了,跑不出来。

    这个题的难点在于解答树的每一层都是无穷多,这导致我们必须要强烈的剪枝!否则绝对没有办法跑完。由于题目的特殊性(拆分),所以我们要尽量剪枝,估计是因为我这个剪的还不够,一到难题就不行了。还有3/997 算不出来的原因有点特别。以后再仔细想想。


    #include <iostream>
    using namespace std;
    int res[10]={0};//用来存储临时结果
    int depth =2;//用来存储现行深度
    int last_min = 1<<30;//用来选取最优的埃及分数最后一项
    int final_res[10]={0};//用来存储最优埃及分数
    bool ok = false;//用来判断是否是合格的深度
    
    //找最大公因数
    int findGCD(int a,int n){
        if(a==0) return 1;
        if(n%a==0)
            return a;
        for(int i=2;i<a;i++){
            if(a%i==0 and n%i==0)
                return i;
        }
        return 1;
    }
    //找最小公倍数
    int findLCM(int a,int n){
        if(n%a==0)
            return n;
        int gcd = findGCD(a,n);
        //16 24 gcd = 8  lcm = 8*2*3
        return a*n/gcd;
    }
    //深度搜索 cur 是光标 m,n 分别是当前要解决的分子分母
    void dfs(int cur,int cur_m,int cur_n){
    	//如果cur 到了最后了
        if(cur==depth){
    	//如果此时分子是0 表示我们找到了一组埃及分数
    	//此时如果最后一个分母比已经记录的要小 我们就要更新了
            if(cur_m==0 and res[cur-1]<last_min){
                ok = true;//表示此深度是合格的
                //得到了结果~~比较之后存储一下
                last_min = res[cur-1];//更新最小
                for(int i=0;i<depth;i++)
                    final_res[i]=res[i];
            }
            return;
        }
        if(cur_n==0 or cur_m==0) return;
        //1/a 必须要小于 m/n 才行!为了加快速度让 a 直接是 n/m
        for(int a=cur_n/cur_m;;a++)if(a*cur_m>=cur_n){
    	//这层剪枝是这样的:如果是该埃及分数序列的第一位
    //且发现 深度*第一位 还比 m/n 小 那就没必要开始了
            if(cur==0 and depth*cur_n<=a*cur_m)
                return;
            //接着要进行减法运算
            int lcm = findLCM(a, cur_n);//通分之后的分母
            int lcm_1 = lcm/a;
            int lcm_m = cur_m*lcm/cur_n;
            int sub = lcm_m-lcm_1;//通分之后做差
            int gcd = findGCD(sub,lcm);
            if(gcd!=1){sub /= gcd;lcm/=gcd;}//化简结果
            if((depth-cur-1)>0 and (depth-cur-1)*lcm<sub*(a+1)){
                //此时要检查有没有继续遍历的必要
    //现在还剩 depth-cur-1个位置没有填 如果发现即使都填1/(a+1)
    //之后也无法填满还剩的部分,所以就减掉
                //剪枝
                return;
            }
            res[cur]= a;//如果都合适,那就存进去
            dfs(cur+1,sub,lcm);//继续搞
            if(cur+1==depth)//如果已经到了结尾 就手动结束
    //这一步比较特别 以前没考虑过这样的地方 这可能是因为无穷的原因
                return;
        }
        return;
    }


  • 相关阅读:
    ajax异步服务器获取时间
    JavaScript基本知识
    JavaScript使用button提交表单
    spring与hibernate整合
    Spring的事务属性
    注解方式实现Spring声明式事务管理
    svn的安装使用
    sbn
    恢复oracle中误删除drop掉的表
    ORA-20000: ORU-10027: buffer overflow, limit of 2000 bytes的解决办法
  • 原文地址:https://www.cnblogs.com/yuchenlin/p/4379254.html
Copyright © 2020-2023  润新知