思路:使用动态规划寻找到考虑所有问题后,机器A运行\(i\)分钟后,机器B运行的时间的最小值。之后再在所有的这\(i\)种情况中找到机器A和机器B共同运行的最小值。
\(dp[i][j]\)表示在做前i个任务中,机器A运行\(j\)分钟的情况下B机器运行的最短时间
解释:
在考虑第\(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]\)的值就可以更小,与假设矛盾。
反证法:\(dp[n][j]\)是问题的解,对应着机器B运行时间的最小值。假设此时机器B的运行时间可以恰当增大,以此来使得总时间最小。那么,有下列三种情况:
一共有\(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;
}
原文:https://www.cnblogs.com/xianyi-yk/p/14654850.html