• 浅谈迭代加深(iddfs)


    引子

    迭代加深搜索的实质就是限制搜索层数的暴搜。在了解DFS的基础上,iddfs其实是很好理解的。只是需要多一个枚举层数的过程再在搜索里面判断一下层数。

    gm的版子(伪代码)

    IDDFS ( int current_depth  ,  int max_depth )   //当前深度,最大深度
    {
           if ( current_depth > max_depth ) return ;
           if ( 找到答案 ) { 输出答案 ; (exit(0) ;  ||  return ;) }
           for each ( 当前节点的儿子节点 )
           {
     	IDDFS ( current_depth+1  ,  max_depth ) ;
           }   
    }
    //在main函数中,调用IDDFS
    for ( int  i = min_depth ; ; i++ )
    {
           IDDFS ( 0 , i ) ;
    }
    
    

    例题

    埃及分数

    题目描述

    在古埃及,人们使用单位分数的和(形如1/a的, a是自然数)表示一切有理数。如:2/3=1/2+1/6,但不允许2/3=1/3+1/3,因为加数中有相同的。对于一个分数a/b,表示方法有很多种,但是哪种最好呢?首先,加数少的比加数多的好,其次,加数个数相同的,最小的分数越大越好。
    如:19/45=1/3 + 1/12 + 1/180
    19/45=1/3 + 1/15 + 1/45
    19/45=1/3 + 1/18 + 1/30,
    19/45=1/4 + 1/6 + 1/180
    19/45=1/5 + 1/6 + 1/18.
    最好的是最后一种,因为1/18比1/180,1/45,1/30,1/180都大。
    给出a,b(0<a<b<1000),编程计算最好的表达方式

    思路

    这道题用暴搜是基本无法实现的。首先我们并不知道需要多少个分数,也不知道最大的分母有多大。其递归层数和深度都是无限的。

    因为我们只需要求到最优解,所以通过枚举深度(从小到大)我们是可以对递归层数进行限制的。那么如何枚举每一个分母的大小呢?
    假设我们需要枚举的分数为(frac{a}{b})
    当前分数的分母一定大于 (frac{b}{a})的所以下界为(frac{b}{a}),那我们如何求上界呢?
    因为我们限制了递归的层数,假设递归的最深层数为(x), 当前层数为(y), 那么 (frac{x - y}{k}) 一定(>) (frac{a}{b})的。
    进行移项后,我们可以得到 (k <= (y - x + 1) imes frac{b}{a})

    代码

    #include <cstdio>
    #include <cstring>
    #include <algorithm> 
    #include <cstdlib>//好东西 
    #define int long long
    using namespace std;
    const int maxn = 1005;
    
    int gcd(int x, int y){
    	if(y == 0)return x;
    	return gcd(y, (x % y));
    }
    int a, b;
    int maxt;
    int ans[maxn * maxn];
    int ans2[maxn * maxn];
    bool flag;
    int t;
    int sum;
    
    //int Fibonacci(int a, int b, int num){
    //	if(b % a == 0)return num;
    //	int Gcd = gcd(a, b);
    //	a /= Gcd;
    //	b /= Gcd;
    //	ans2[num] = (b / a + 1);
    //	a = (b / a) * a - b;
    //	b *= (b / a);
    //	return Fibonacci(a, b, num + 1);
    //}
    
    void dfs(int a, int b, int num, int maxt){
    	if(num > maxt)return;
    	int Gcd = gcd(a, b);
    	a /= Gcd;
    	b /= Gcd;
    //	if(b % a == 0){
    //		ans[num] = b / a;
    //		if(ans[num] > ans[num - 1]){
    //			if(num == sum && num <= maxt && ans[num] < ans[sum]){
    //				for(int i = 1; i <= num; i ++){
    //					ans2[i] = ans[i];
    //				}
    //			}
    //			if(num <= maxt && (num < sum || !flag)){
    //				for(int i = 1; i <= num; i ++){
    //					ans2[i] = ans[i];
    //				}
    //			}
    //			flag = 1;
    //			sum = num;
    //		}
    //		return;
    //	}
    	if(b % a == 0 && (b / a) > ans[num - 1]){
    		ans[num] = b;
    		if(!flag || ans[num] < ans2[num]){
    			for(int i = 1; i <= num; i ++){
    				ans2[i] = ans[i];
    			}
    			flag = 1;
    			sum = num; 
    		}
    		return;
    	}
    	int s = b / a + 1;
    	if(s <= ans[num - 1])s = ans[num - 1] + 1;
    	int t = (maxt - num + 1) * (b / a);
    	if(flag && t >= ans2[sum])t = ans2[sum] - 1; 
    	for(int i = s; i <= t; i ++){
    		ans[num] = i;
    		dfs(a * i - b, b * i, num + 1, maxt);  
    	}
    }
    signed main() {
    	scanf("%lld %lld", &a, &b);
    //	int t = Fibonacci(a, b, 1);
    	for(int i = 1; ; i ++){
    		flag = 0;
    		dfs(a, b, 1, i);
    		if(flag){
    			for(int j = 1; j <= sum; j ++){
    				printf("%lld ", ans2[j]);
    			}
    			return 0;
    		}
    	}
    	return 0;
    }
    
    夜空中最亮的星,请照亮我前行
  • 相关阅读:
    Ubuntu16.04 LTS 安装VNC Server开启远程桌面
    duilib List右键菜单的响应
    centos bootloader安装到u盘后修复方法
    dpkg: error processing package XXX (--configure) 解决方法 (ubuntu右上角红色警告)
    linux centos ftp服务器搭建
    windows 端口转发 netsh
    遍历windows窗口
    解除文件占用
    VS 运行库MT、MD的区别
    点击显示桌面的窗口状态
  • 原文地址:https://www.cnblogs.com/Nefelibata/p/14400908.html
Copyright © 2020-2023  润新知