雙核處理(動態規劃的01揹包問題)

許佳佳233發表於2017-05-18

題目

一種雙核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

分析:

1、要讓雙核CPU執行的時間最少,其實就是要讓兩個核儘量同時結束。也就是要讓一個核所執行的時間儘量逼近執行總時間的一半,也就是sum/2。
2、這樣其實就將題目轉化成了一個01揹包問題。筆者對於01揹包問題之前都是通過“深度優先搜尋+回溯”的方式解決,但是在使用的時候往往會讓複雜度過高或者執行時間過長,此例使用的是動態規劃方式。
3、題目中其實有提示使用動態規劃的01揹包方式,題目中強調了“每個數均為1024的倍數”。

思路:

1、由於需要用總時間來建立陣列,因此接收到資料後統一除以1024後儲存。(最後輸出的時候乘以1024)
2、i代表揹包中處理了i個任務(可能裝入可能不裝入),j代表目前揹包中有j的空間可以存放。
3、如果放入任務時間超過j,也就是p[i]>j,那麼揹包中就無法再放入任務,所以dp[i + 1][j] = dp[i][j]。反之,有兩種可能,可能放入也可能不放入,這取決於此時放入的物品的價效比有沒有之前放入的物品的價效比高,如果放入那麼就為dp[i + 1][j] = dp[i][j - p[i]] + p[i],如果不放入就為dp[i + 1][j] =dp[i][j]。
4、最後附上這道題的陣列例項:

0 0 0 0 0 0 0 0 0 
0 0 0 3 3 3 3 3 3 
0 0 0 3 3 3 6 6 6 
0 0 0 3 3 3 6 7 7 
0 0 0 3 3 3 6 7 7 
0 1 1 3 4 4 6 7 8  

程式碼:

import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);

        int n = scan.nextInt();
        int[] p = new int[n];
        int sum = 0;
        for (int i = 0; i < n; i++) {
            p[i] = scan.nextInt() / 1024;
            sum += p[i];
        }

        int[][] dp = new int[n + 1][sum / 2 + 1];
        for (int i = 0; i < n; i++)
            for (int j = 1; j <=sum / 2; j++) {
                if (j < p[i])
                    dp[i + 1][j] = dp[i][j];
                else
                    dp[i + 1][j] = Math.max(dp[i][j], dp[i][j - p[i]] + p[i]);
            }

        System.out.println((sum - dp[n][sum / 2]) * 1024);
    }

}

相關文章