求解双核处理问题(动态规划法)

题目:求解双核处理问题。一种双核CPU的两个核能够同时处理任务,现在有n个已知数据量的任务需要交给CPU处理,假设已知CPU的每个核1秒可以处理1KB,每个核同时只能处理一项任务,n个任务可以按照任意顺序放入CPU进行处理。编写一个程序求出一个设计方案让CPU处理完这批任务所需的时间最少,求这个最少的时间。(提示:完成n个任务需要sum时间,放入两个核中执行,假设第-个核的处理时间为n1,第二个核的处理时间为sum-n1,并假设n1ssum/2,sum-n1zsum/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

算法思想:
对于每个任务 length[i],采用倒序遍历法更新 dp 数组,确保每个任务只被选用一次:
对于j从target到length[i](倒序),如果 dp[j-length[i]]为true,则设 dp[j]为 true。
这样,每个任务都会尝试“加入“已有的可达状态,形成新的可达状态。 

1.基本思路:
将任务分配问题转化为一个 0/1 背包/子集和问题。
总任务时间为 sum
目标是将任务分成两部分,使得一部分的和 n1尽量接近 sum/2
这样,另一部分的和为 sum-n1,两部分中较大的那个就是最终所需的时间。。
因此问题转化为:在所有任务中找出一个子集,使其总和尽可能接近 sum/2。
2.求解方法
使用动态规划(DP)方法来解决子集和问题:
设定 dp[j] 表示是否可以选出若干任务使得任务总和恰好为j。
初始化 dp[0]= true,表示 0时间一定可达。
然后遍历每个任务,对于任务长度为length[i],更新 dp[j],使得如果 dp[j-length[i]]为true,则 dp[j]也为 true(注意倒序更新,以保证每个任务仅使用一次)。
3.求最终答案
令目标 target = sum/2,从 target 向下找出第一个 dp[i]== true 的位置,该位置的值即为可以达到的最大子集和 n1。
最终所需时间为 max(n1,sum-n1),即两个核中处理时间较大的一端。

void solve() {
    long sum = 0;  // 计算所有任务总时间
    for (int i = 0; i < n; i++) {
        sum += length[i];
    }
    long target = sum / 2;  // 希望第一核处理的时间尽量接近 sum/2

    // 定义 dp 数组,大小设置为 102400+1(题目中 n<=100 且每个任务为1024的倍数,最大总和不超过 102400)
    const int MAX = 102400 + 1;
    // 使用 static 避免重复分配(同时确保数组大小为编译时常量)
    static bool dp2[MAX] = {false};
    dp2[0] = true;  // 初始化,0 时间必然可达

    // 0/1 背包动态规划:倒序遍历,防止重复选取同一任务
    for (int i = 0; i < n; i++) {
        // 当任务长度超过 target 时,无需处理
        for (int j = target; j >= length[i]; j--) {
            if (dp2[j - length[i]]) {
                dp2[j] = true;
            }
        }
    }

    // 从 target 开始向下找,找到第一个可达的值
    for (int i = target; i >= 0; i--) {
        if (dp2[i]) {
            // 输出两个核中较大的处理时间,用条件运算符代替 std::max
            cout << ((i > (sum - i)) ? i : (sum - i)) << endl;
            return;
        }
    }
}

输出结果:但是发现还是有一个测试点未过,猜测应该是数组越界

于是添加#include <vector>

去使用 vector<bool> 这样可以根据 target 的实际值动态分配所需空间,避免固定数组大小引起的段错误。

 

测试通过。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值