回溯——用贝尔曼法则优化最优加工顺序问题

1.问题分析

之前的博客https://blog.csdn.net/Jayphone17/article/details/102996649

我们用回溯法解决了机器零件加工最优加工顺序问题

我们分析一下那个情况的复杂度:

(1)时间复杂度,如图所示:

最坏情况下,除了最后一层外,有1+n+n(n-1)+…+n(n-1)(n-2)…≤ nn!个结点需要判断限界函数,判断限界函数需要O(1)的时间,因此耗时O(nn!)。在叶子结点记录最优解耗时O(n),最坏情况下会搜索每一个叶子结点,叶子个数有n!,耗时O(nn!)。最后时间复杂度是O(nn!)≈O((n+1)!)。

(2)空间复杂度。使用了x[ ]数组记录最长路径作为可行解,空间复杂度是O(n)

使用贝尔曼规则进行优化,时间复杂度可以达到O(nlogn)

假设在S集合中加工顺序中,最有加工方案只有以下两种方案之一:

  • 先加工i号零件,再加工j号零件,其他工件加工顺序是最优
  • 先加工j号零件,再加工i号零件,其他工件加工顺序是最优

根据贝尔曼的推导公式:https://blog.csdn.net/Jayphone17/article/details/103013335

方案1比方案优的充分必要条件是:max{ t1j,t2i } ≥ max{ t1i,t2j }。

继续分析之后:

由此可以得到贝尔曼规则:

  • 第一台机器上加工时间越短的工件越先加工
  • 第二台机器上加工时间越短的工件越后加工
  • 第一台机器上加工时间小于第二台机器上加工时间的先加工
  • 第一台机器上加工时间大于等于第二台机器上加工时间的后加工

2.算法设计

一、

(1)根据贝尔曼规则可以把零件分成两个集合:N1={ i | t1i < t2i } ,即第一台机器上加工的时间小于第二台机器上加工时间;

         N2={ i | t1i >= t2i } ,即第一台机器上加工的时间大于等于第二台机器上加工时间

(2)将N1工件按照 t1i 非递减排序,将N2中的工件按照 t2i 非递增排序。

(3)N1中工件接N2中工件,即N1N2就是所求的满足贝尔曼规则的最优加工顺序。

二、

因为C++中可以自定义排序函数的优先级,因此先定义优先级cmp,然后调用sort函数即可。

bool cmp(node a,node b)
{
    return min(b.x,a.y)>=min(a.x,b.y);
}
sort (T,T+n,cmp);

具体这个优先级是什么意思呢?

例如现在有a,b两个零件,在第一台机器加工时间是x,在第二台机器上加工时间是y。

min(b.x,a.y)=min(10,7)=7。

min(b.y,a.x)=min(2,3)=2。

min(b.x,a.y)≥ min(b.y,a.x)。// 贝尔曼规则!!!!

因此a零件加工排在b前面。

3.源代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;

 const int MX=11111;
 int n;
 struct node
 {
     int x;
     int y;
     int id;
 }T[MX];

 bool cmp(node a,node b)
 {
     return min(b.x,a.y) >=min(b.y,a.x);//贝尔曼规则条件的排序
 }

int main()
{
    cout << "请输入机器零件的个数n:"<< endl;
    cin>> n;
    cout << "请依次输入每个机器零件在第一台机器上的加工时间x和第二台机器上的加工时间y:"<< endl;
    for (int i=0;i<n;i++)
    {
        cin >> T[i].x >> T[i].y;
        T[i].id=i+1;
    }
    sort(T,T+n,cmp);
    int f1=0;
    int f2=0;
    for (int i=0;i<n;i++)
    {
        f1+=T[i].x;
        f2=max(f1,f2)+T[i].y;
    }
    cout << "最优的机器零件加工顺序是:"<< endl;
    for (int i=0;i<n;i++)
    {
        cout << T[i].id ;
    }
    cout << endl;
    cout << "最优的零件加工时间是:"<< endl;
    cout << f2 << endl;
    return 0;
}

4.结果测试 

最后的时间复杂度是O(nlogn)。

最后的空间复杂度是O(n)。

发布了57 篇原创文章 · 获赞 9 · 访问量 3604

猜你喜欢

转载自blog.csdn.net/Jayphone17/article/details/103038988