每日一题(6) 求解双核处理问题

求解双核处理问题。一种双核CPU的两个核能够同时处理任务,现在有n个已知数据量的任务需要交给CPU处理,假设已知CPU的每个核1秒可以处理1KB,每个核同时只能处理一项任务,n个任务可以按照任意顺序放入CPU进行处理。编写一个程序求出一个设计方案让CPU处理完这批任务所需的时间最少,求这个最少的时间。(提示:完成n个任务需要sum时间,放入两个核中执行,假设第一个核的处理时间为n1,第二个核的处理时间为sum-n1,并假设n1≤sum/2,sum-n1≥sum/2,要使处理时间最小,则n1越来越靠近sum/2,最终目标是求max(n1,sum-n1)的最大值。

函数接口定义:

void solve();

裁判测试程序样例:

#include <iostream> using namespace std; 
#define M 100 long length[M]; 
long dp[M]={0}; 
int n; 
void solve(); 
int main() { 
    void solve(); 
    cin>>n; 
    for(int i=0;i<n;i++)
        //输入任务长度 
        cin>>length[i]; 
        solve(); 
        return 0; 
} 

/* 请在这里填写答案 */

输入格式:

第一行输入一个整数n表示任务数,第二行再依次输入n个数,每个数表示任务长度,单位为KB(每个数均为1024的倍数)。

输出格式:

输出一个整数表示最少需要处理的时间。

输入样例1:

5
3072 3072 7168 3072 1024

输出样例1:

9216

 

问题分析

这个问题本质上是一个划分问题。我们需要将 n 个任务分配到两个处理器上,使得处理时间最短。由于两个处理器是并行工作的,因此总的处理时间取决于处理时间较长的那个处理器。

如果任务的总长度为 sum,我们希望将任务分成两部分,尽量使得两部分的时间接近 sum/2。这样可以使得最长的处理时间最小。

形式化地说,如果我们用 n1 表示第一个处理器的处理时间,sum-n1 表示第二个处理器的处理时间,则总的处理时间为 max(n1, sum-n1)。而当 n1 = sum-n1 = sum/2 时,总处理时间最小。由于任务是离散的,我们无法总是实现完美的平分,因此问题转化为:找到一个尽可能接近但不超过 sum/2 的 n1。

解题思路

这个问题可以使用动态规划来解决,具体来说,是一个0-1背包问题的变形:

  • 我们有 n 个物品(任务),每个物品的重量(时间)是 length[i]
  • 背包容量是 sum/2
  • 我们需要找到一种装包方式,使得背包内物品的总重量尽可能接近但不超过 sum/2

然而样例程序中背包容量上限定义为M=100,且各个任务长度严格满足1024 的倍数,因此我们可以把背包容量定义为sum/2048。

动态规划解法

我们使用一维滚动数组,定义 dp[j] 表示容量为 j 的背包能装入的最大重量。

状态转移方程为:

dp[j] = max(dp[j], dp[j-length[i]/1024] + length[i]/1024)

其中,j 表示背包容量(单位为秒),length[i]/1024 表示处理第 i 个任务所需的时间(秒)。

最终,两个半区间的最大值,即max(dp[half/1024] * 1024, sum - dp[half/1024] * 1024) 就是我们所求的最小处理时间。

代码实现

void solve(){
    int sum = 0;
    for(int i=0;i<n;i++){
        sum += length[i];
    }
    int half = sum/2;

    for(int i=0;i<n;i++){
        for(int j=half/1024;j>=length[i]/1024;j--){
            dp[j] = max(dp[j], length[i]+dp[j-length[i]/1024]);
        }
    }
    long maxValue = max(dp[half/1024], sum-dp[half/1024]);
    printf("%ld", maxValue);
}

普通01背包问题,为了避免出现数据叠加,第二层遍历需采用从大到小的方式。若为完全背包问题则无这个考量。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值