双核处理问题(2017网易春招)

来源:互联网 发布:网络道德的原则有 编辑:程序博客网 时间:2024/06/07 22:38

问题描述



问题分析

刚开始做这题思路比较简单:将任务时间按照从大到小的排序,两个CPU为A和B,每次将任务放进CPU前比较A和B的大小,若A>B,则B+=task[i];否则A+=task[i],最后返回A和B中较大者。其实这种做法是不对的,比如一个序列 9 8 7 6 4,若按照上述思路得到的CPU最短处理时间为21=max(9+6+4 ,8+7),其实还有更优的方案为17=max(9+8, 7+6+4)。凡事不能想当然,最后还是选择用01背包算法来解。


假设A和B正好处理相同时间的任务,则A=B=sum/2,sum为总的任务时间,最小处理时间为max(A,B)=sum/2;但是实际情况可能A+B=sum,但A<B,此时A越接近sum/2则最小处理时间max(A,B)=B=sum-A也越小。可将sum/2设为A的上限值,即背包的的最大容量,现在将每件任务放入A中,要求放入任务的时间和小于sum/2,但又要使和最大。

根据背包算法的思路:


*  只考虑第i个任务task[i],若第i个任务不加入A,则问题转化为“前i-1个任务放入容量为sum/2的A中”;
*  若第i个任务加入A,则问题转化为“前i-1个任务放入剩下容量为sum/2-task[i]的A中”。


关键伪代码:for i = 0 ... n-1for j = sum/2 ... task[i]dp[j] = max(dp[j - task[i]] + task[i], dp[j]);


代码实现

#include <iostream>#include <algorithm>using namespace std;int n;//处理任务数int task[50];//存储任务数组int sum;//任务总时间int main(void){//输入cin >> n;//int task[5] = { 3072, 3072, 7168, 3072, 1024 };for (int i = 0; i < n; i++){cin >> task[i];task[i] /=  1024;sum += task[i];}int *dp = new int[sum / 2];memset(dp, 0, sizeof(int)*(sum / 2));/* 0-1背包算法*  背包容量即sum/2为总重量(任务总时间sum/2),每个任务task[i]即为将要放入背包的物品,背包的最大价值即为放入背包(CPU)的总重量(任务总时间)。*  只考虑第i个任务task[i],若第i个任务不加入A,则问题转化为“前i-1个任务放入容量为sum/2的A中”;*  若第i个任务加入A,则问题转化为“前i-1个任务放入剩下容量为sum/2-task[i]的A中”。*/for (int i = 0; i < n; i++)for (int j = sum / 2; j >= task[i]; j--)/* dp[j - task[i]] + task[i]-->加入A;dp[j]-->不加入A */dp[j] = max(dp[j - task[i]] + task[i], dp[j]);cout << (sum - dp[sum / 2]) * 1024 << endl;return 0;}




0 0