独立问题最优调度的算法合理性分析(详解)(附代码)
作者:互联网
思路:使用动态规划寻找到考虑所有问题后,机器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;
}
标签:运行,机器,int,最小值,机器运行,算法,详解,合理性,dp 来源: https://www.cnblogs.com/xianyi-yk/p/14654850.html