名企笔试:网易游戏2016招聘笔试题(双核处理)
一种双核CPU的两个核能够同时的处理任务,现在有n个已知数据量的任务需要交给CPU处理,假设已知CPU的每个核1秒可以处理1kb,每个核同时只能处理一项任务。n个任务可以按照任意顺序放入CPU进行处理,现在需要设计一个方案让CPU处理完这批任务所需的时间最少,求这个最小的时间。
输入描述:
输入包括两行:
第一行为整数n(1 ≤ n ≤ 50)
第二行为n个整数length[i](1024 ≤ length[i] ≤ 4194304),表示每个任务的长度为length[i]kb,每个数均为1024的倍数。
输出描述:
输出一个整数,表示最少需要处理的时间
输入例子:
5
3072 3072 7168 3072 1024
输出例子:
9216
分析:
如何才能使的运算的时间最少呢?当然是使得两个CPU都能达到最高的效率,就是是的来个CPU尽可能在同时的完成所有的任务,此时就是将任务分成两份,使得两份的时间的和的差尽可能的小。
突然发现的一个半背包问题,就是用一个容量是所有任务的时间的总和的一半,尽可能的装入更多的任务,让一个CPU完成,剩下的所有的任务用另一个CPU来完成。两个CPU运行的最长时间就是运行所有任务的最少时间。
仿佛问题已经解决了,但是注意到(1 ≤ n ≤ 50)和(1024 ≤ length[i] ≤ 4194304)所有的任务的和最大能达到50* 4194304。如果我们用背包问题,空间超出限制。我们需要使用另一种方法了?不用啊,所有的任务都是1025的倍数,我们可以讲所有的任务除以1024,之后最大的和就是50*4096。
Code:
#include<iostream>
#include<string.h>
#include<algorithm>
#include<math.h>
using namespace std;
const int MAXN = 50 * 4096 + 5;
int cpu[MAXN],a[55];
int main()
{
int n,b;
while(cin>>n){
memset(cpu,0,sizeof(cpu));
int sum = 0;
for(int i=0;i<n;i++){
cin>>b;
a[i] = b / 1024;
sum += a[i];
}
int sum1 = sum / 2;
// cout<<sum1<<" "<<sum<<endl;
cpu[0] = 1;
for(int i=0;i<n;i++){
for(int j=sum1;j>=a[i];j--){
cpu[j] = cpu[j] | cpu[j - a[i]];
}
}
while(cpu[sum1] == 0) sum1--;
// cout<<sum1<<endl;
cout<<(sum - sum1) * 1024<<endl;
}
return 0;
}