Java教程

独立问题最优调度的算法合理性分析(详解)(附代码)

本文主要是介绍独立问题最优调度的算法合理性分析(详解)(附代码),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

思路:使用动态规划寻找到考虑所有问题后,机器A运行\(i\)分钟后,机器B运行的时间的最小值。之后再在所有的这\(i\)种情况中找到机器A和机器B共同运行的最小值。

子问题:

\(dp[i][j]\)表示在做前i个任务中,机器A运行\(j\)分钟的情况下B机器运行的最短时间

子问题之间的转移方程:

\[dp[i][j] = min(dp[i-1][j]+b[i],dp[i-1][j-a[i]]) \]

解释:

在考虑第\(i\)个任务时,机器B在机器A运行\(j\)分钟的情况下的最小值应该是

前\(i-1\)个任务机器B在A运行\(j\)分钟的情况下的最小值加上B机器运行第\(i\)个任务的时间

以及将这个任务交给A机器运行前\(i-1\)个任务中A机器运行\(j-a[i]\)分钟时,B机器运行时间的最小值。

最优子结构的证明:

当\(dp[i][j]\)取到最优时,如果前\(i-1\)个任务机器B在A运行\(j\)分钟的最短时间\(dp[i-1][j]\)还可以更短,或者如果前\(i-1\)个任务机器B在A运行\(j-a[i]\)分钟的最短时间还可以更短,那么\(dp[i][j]\)的值就可以更小,与假设矛盾。

为何本问题的解一定对应着机器B的时间要取最小值?

反证法:\(dp[n][j]\)是问题的解,对应着机器B运行时间的最小值。假设此时机器B的运行时间可以恰当增大,以此来使得总时间最小。那么,有下列三种情况:

  • 如果此时机器B运行的时间本来就比机器A运行的时间更长,如果机器B的运行时间变长,那么显而易见,这会使得结果变差,因此不成立。
  • 如果此时机器B运行的时间比机器A更短,机器B运行时间变长而机器A运行时间也变长或不变,这不会使结果变得更好,因此不成立。
  • 如果此时机器B运行的时间比机器A更短且机器B运行时间变长而机器A运行时间变短,那么一定可以在\(dp[n][j]\)这个序列中找到对应的\(j'<j\)使得\(dp[n][j']<dp[n][j]\),那么\(dp[n][j]\)不会是该问题的解,因此矛盾。

算法复杂度分析:

一共有\(n\)种物品,所有物品的和为\(s\),因此子问题的规模大概是\(n*s\)个,解决一个子问题需要的复杂度为\(O(1)\),因此算法复杂度为\(O(sn)\),由于\(s\)可以特别大,所以这个算法不适用于\(s\)特别大的情况。

代码如下:

#include <iostream>
#include <algorithm>
using namespace std;

int dp[105][10024];
int a[105];
int b[105];
int main()
{
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    for (int i = 1; i <= n; i++)
        cin >> b[i];
    int sum = 0;
    for (int i = 1; i <= n; i++)
    {
        sum += a[i]; //只考虑前i个,因此花时间最多不会超过前i个之和
        for (int j = 0; j <= sum; j++)
        {
            int cur_val = 0x3f3f3f3f;
            if (j - a[i] >= 0)
                cur_val = dp[i - 1][j - a[i]];
            dp[i][j] = dp[i - 1][j] + b[i];
            if (dp[i][j] > cur_val)
                dp[i][j] = cur_val;
        }
    }
    int ans = 0x3f3f3f3f;
    for (int i = 0; i <= sum; i++)
        if (ans > max(dp[n][i], i))
            ans = max(dp[n][i], i);
    for (int i = 1; i <= n; i++)
    {
        for (int j = 0; j <= sum; j++)
            cout<<dp[i][j]<<" ";
        cout<<endl;
    }
    cout << ans << endl;
    return 0;
}

这篇关于独立问题最优调度的算法合理性分析(详解)(附代码)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!