埃及分數(迭代加深搜索)

迭代加深搜索,實質上是限定下界的深度優先搜索。即首先允許深度優先搜索K層,若沒有發現可行解,再將K+1後重復以上步驟搜索,直到搜索到可行解。

迭代搜索深度是一個比較炫酷的搜索方式,不過有點拿時間換空間的感覺。

首先迭代深度比較搓的寫法是,首先設置一個閥值MaxH,初始爲最小值。當在搜索深度Depth <= MaxH時找到解則此時爲最優解,否則MaxH++,繼續深搜。

另外一種比較吊的寫法是二分搜索深度,若搜到則減小閥值,否則增大閥值。

總之,迭代深度搜索就是通過改變深搜的深度來尋找最優解,這樣做的好處是省掉了BFS中狀態標記所有的空間花銷。

在迭代加深搜索的算法中,連續的深度優先搜索被引入,每一個深度約束逐次加1,直到搜索到目標爲止。這樣可以看出重複搜索了好多。但是它的好處在於:

1.空間開銷小 每個深度下實際上是一個深度優先搜索,不過深度有限制,而DFS的空間消耗小是衆所周知的。
2.利於深度剪枝
3.時間效率不低 雖然重複搜索,但是大家不難理解,前一次搜索跟後一次相不是微不足到的。

我們可以看出,迭代加深搜索算法就是仿廣度優先搜索的深度優先搜索。既能滿足深度優先搜索的線性存儲要求,又能保證發現一個最小深度的目標結點。

從實際應用來看,迭代加深搜索的效果比較好,並不比廣度優先搜索慢很多,但是空間複雜度卻與深度優先搜索相同,比廣度優先搜索小很多。

使用搜索算法的時候,選擇正確的搜索方式很重要。當有一類問題需要做廣度優先搜索,但卻沒有足夠的空間,而時間卻很充裕,碰到這類問題,我們可以選擇迭代加深搜索算法。

大家可以百度一下埃及分數的題面,沒有確認到哪個oj有這個題目,也不知道哪裏流傳出來的……

#include <iostream>
#include <string.h>
#include <stdio.h>

using namespace std;
typedef long long LL;
const int INF = ~0U>>1;
const int N = 10;

int dep,flag;
int ans[N],d[N];

int gcd(int a,int b)
{
    return b ? gcd(b,a%b):a;
}

void dfs(int a,int b,int k)
{
    if(k == dep + 1) return;
    if(b % a == 0 && b / a > d[k-1])
    {
        d[k] = b / a;
        if(!flag || d[k] < ans[k])
             memcpy(ans,d,sizeof(d));
        flag = 1;
        return;
    }
    int s = b / a;
    if(s <= d[k-1]) s = d[k-1] + 1;
    int t = (dep - k + 1) *  b / a;
    if(t > INF / b) t = INF / b;
    if(flag && t >= ans[dep]) t = ans[dep] - 1;
    for(int i=s;i<=t;i++)
    {
        d[k] = i;
        int m = gcd(i*a - b,b*i);
        dfs((i*a-b)/m,b*i/m,k+1);
    }
}

void Work(int a,int b)
{
    d[0] = 1;
    flag = 0;
    for(dep=1;dep <= N;dep++)
    {
        dfs(a,b,1);
        if(flag)
        {
            printf("1/%d",ans[1]);
            for(int i=2;i<=dep;i++)
                printf("+1/%d",ans[i]);
            cout<<endl;
            break;
        }
    }
}

int main()
{
    int a,b;
    while(cin>>a>>b)
    {
        cout<<a<<"/"<<b<<"=";
        Work(a,b);
    }
    return 0;
}
發佈了69 篇原創文章 · 獲贊 101 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章