【算法学习笔记】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;
}


你可能感兴趣的:(学习笔记)