算法设计与分析: 3-1 独立任务最优调度问题(双机调度问题)

3-1 独立任务最优调度问题(双机调度问题)


问题描述

用2台处理机A和B处理n个作业。设第i个作业交给机器A处理时需要时间 ai a i ,若由机器B来处理,则需要时间 bi b i 。由于各作业的特点和机器的性能关系,很可能对于某些i,有 aibi a i ≥ b i ,而对于某些j,j≠i,有 ajbj a j < b j 。既不能将一个作业分开由2台机器处理,也没有一台机器能同时处理2个作业。设计一个动态规划算法,使得这2台机器处理完这n个作业的时间最短(从任何一台机器开工到最后一台机器停工的总时间)。研究一个实例: (a1,a2,a3,a4,a5,a6)(2,5,7,10,5,2)(b1,b2,b3,b4,b5,b6)(3,8,4,11,3,4) ( a 1 , a 2 , a 3 , a 4 , a 5 , a 6 ) = ( 2 , 5 , 7 , 10 , 5 , 2 ) ; ( b 1 , b 2 , b 3 , b 4 , b 5 , b 6 ) = ( 3 , 8 , 4 , 11 , 3 , 4 )
对于给定的2 台处理机A和B处理n个作业,找出一个最优调度方案,使2台机器处理完这n个作业的时间最短。

数据输入
输入数据的第1行是1个正整数n(n≤200), 表示要处理n个作业。接下来的2行中,每行有n个正整数,分别表示处理机A和B处理第i个作业需要的处理时间。


分析

全排列法

对于n个作业中的每个作业,要么由机器A处理,要么由机器B处理。可以设计一个n位的二进制序列,某一位上为1,由机器A处理,为0由机器B处理。机器A、机器B处理n个作业的所有情况,对应于该n位二进制的全排列。可见,可以转化为n位二进制全排列问题,共有 2n 2 n 种情况。

动态规划法

递推关系一

假设 p(i,j,k) p ( i , j , k ) 表示前 k k 个任务在机器A处理不超过时间 i i ,机器B处理不超过时间 j j 内完成,为boolean型。
p(i,j,k)=p(iak,j,k1)||p(i,jbk,k1) p ( i , j , k ) = p ( i − a k , j , k − 1 ) | | p ( i , j − b k , k − 1 ) 前提是 i>=ak,j>=bk i >= a k , j >= b k
p(i,j,0)=1 p ( i , j , 0 ) = 1
最终的最短处理时间为 min{max{i, j}}

递推关系二

假设T[i][j],表示 完成 前i个任务,在机器A花费小于等于j的时间的前提下,机器B所需要花费的最少时间。
1.如果时间j小于a[i],那么第i个任务只可能由机器B完成:T[i][j] = T[i-1][j] + b[i];
2.如果时间j大于或等于a[i],那么须要考虑第i个任务是由机器A还是由机器B处理好:
(1)若由机器A处理:T[i][j] = T[i-1][j-a[i]]
(2)若由机器B处理:T[i][j] = T[i-1][j] + b[i]
可见此时,T[i][j] = MIN{T[i-1][j-a[i]], T[i-1][j] + b[i]}

最后,比较 j与T[n][j],取较大者(机器A、机器B最后都要处理完成),即:MAX{j, T[n][j]}
遍历j的所有情况,取最小者,即:MIN{MAX{j, T[n][j]}} 0<=j<=sum
sum为机器A单独完成所有任务所须花费的时间
注意:机器A与机器B花费的时间先分开考虑


全排列法

Java

import java.util.Scanner;

public class DuLiRenWuZuiYouDiaoDu {

    public static void main(String[] args){
        int[] a,b;
        int n,i,j,temp;
        int result = 10000;
        int sa,sb;

        /*
        input data:
        6
        2 5 7 10 5 2
        3 8 4 11 3 4
        */
        Scanner input = new Scanner(System.in);

        while (true){

            n = input.nextInt();
            a=new int[n];
            b=new int[n];

            for(i=0;ifor(i=0;i//n位二进制的全排列,000000 --> 111111,假设为1时,A机处理;为0时,B机处理
            for(i=0;i2,n);i++)
            {
                sa=0;sb=0;temp=i;
//                for(j=0; j
                for(j=n-1; j>=0; j--)
                {
                    if(temp%2 == 1) //最后一位为1,A机处理
                        sa += a[j];
                    else
                        sb += b[j]; //最后一位为0,B机处理

                    temp = temp/2; //可以看成二进制右移一位
                }
                temp = sa > sb ? sa : sb;
                result = result > temp ? temp : result;
            }

            System.out.println(result);
        }
    }
}

动态规划法

递推关系一

Java

import java.util.Scanner;

public class DuLiRenWuZuiYouDiaoDu1 {
    private static int n;
    private static int[] a;
    private static int[] b;
    private static boolean[][][] p;

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

        while (true){
            n = sc.nextInt();
            a = new int[n + 1];
            b = new int[n + 1];

            for (int i = 1; i <= n; i++) {
                a[i] = sc.nextInt();
            }
            for (int i = 1; i <= n; i++) {
                b[i] = sc.nextInt();
            }

            int max1 = getMaxValue(a, n);
            int max2 = getMaxValue(b, n);
            int mx = max(max1, max2);  //单个作业完成任务所需时间最大值
            int mn = mx * n;  //所有任务完成时间上限

            p = new boolean[mn + 1][mn + 1][n + 1];

            int result = schedule(n, mn);

            System.out.println(result);
        }
    }

    /*
    假设p(i, j, k)表示前k个任务在机器A处理不超过时间i,在机器B处理不超过时间j内完成,为boolean型
    p(i, j, k) = p(i-ak, j, k-1) || p(i, j-bk, k-1)  前提是i>=ak, j>=bk
    p(i, j, 0) = 1
    最短处理时间为 min{max{i, j}}
    */
    private static int schedule(int n, int mn) {
        for (int i = 0; i <= mn; i++)
            for (int j = 0; j <= mn; j++) {
                p[i][j][0] = true;
                for (int k = 1; k <= n; k++)
                    p[i][j][k] = false;
            }
        for (int k = 1; k <= n; k++)
            for (int i = 0; i <= mn; i++)
                for (int j = 0; j <= mn; j++) {
                    if (i >= a[k])
                        p[i][j][k] = p[i - a[k]][j][k - 1];
                    if (j >= b[k])
                        p[i][j][k] = (p[i][j][k] || p[i][j - b[k]][k - 1]);
                }
        int opt = mn;
        int temp;
        for (int i = 0; i <= mn; i++)
            for (int j = 0; j <= mn; j++)
                if (p[i][j][n]) {
                    temp = max(i, j);
                    if (temp < opt)
                        opt = temp;
                }
        return opt;

    }

    //返回数组c[1,n]中的最大值
    private static int getMaxValue(int c[], int n) {
        int mx = c[1];
        for (int i = 2; i <= n; i++)
            if (c[i] > mx)
                mx = c[i];
        return mx;
    }

    private static int max(int a, int b) {
        return a > b ? a : b;
    }

}

递推关系二

Java: version 1

import java.util.Scanner;

public class DuLiRenWuZuiYouDiaoDu3 {

    private static int[][] T;
    private static int[] a;
    private static int[] b;

    /*
    注意:机器A与机器B花费的时间先分开考虑
    假设T[i][j],表示 完成 前i个任务,在机器A花费小于等于j的时间的前提下,机器B所需要花费的最少时间。
    1.如果时间j小于a[i],那么第i个任务只可能由机器B完成:T[i][j] = T[i-1][j] + b[i];
    2.如果时间j大于或等于a[i],那么须要考虑第i个任务是由机器A还是由机器B处理好:
        1)若由机器A处理:T[i][j] = T[i-1][j-a[i]]
        2)若由机器B处理:T[i][j] = T[i-1][j] + b[i]
        可见此时,T[i][j] = MIN{T[i-1][j-a[i]], T[i-1][j] + b[i]}

    最后,比较 j与T[n][j],取较大者(机器A、机器B最后都要处理完成),即:MAX{j, T[n][j]}
    遍历j的所有情况,取最小者,即:MIN{MAX{j, T[n][j]}} 0<=j<=sum sum为机器A单独完成所有任务所须花费的时间
    */
    public static void main(String[] args) {
        int i, j, n;
        int sum, time;
        Scanner input = new Scanner(System.in);

        while (true) {
            sum = 0;

            n = input.nextInt();
            a = new int[n + 1];
            b = new int[n + 1];
            T = new int[100][100];

            for (i = 1; i <= n; i++) {
                a[i] = input.nextInt();
                sum += a[i];
            }
            for (i = 1; i <= n; i++) {
                b[i] = input.nextInt();
            }

            for(i=1; i<=n; i++)
                for(j=0; j<=sum; j++)
                    if(j >= a[i])
                        T[i][j] = MIN(T[i-1][j-a[i]], T[i-1][j]+b[i]);
                    else
                        T[i][j] = T[i-1][j] + b[i];

            time = Integer.MAX_VALUE;
            for (j = 0; j <= sum; j++)
                time = MIN(time, MAX(j, T[n][j]));

            System.out.println(time);
        }
    }

    private static int MAX(int a, int b) {
        return a > b ? a : b;
    }

    private static int MIN(int a, int b) {
        return a > b ? b : a;
    }
}

Java: version 2

import java.util.Scanner;

public class DuLiRenWuZuiYouDiaoDu2 {

    private static int[] T;
    private static int[] a;
    private static int[] b;


    public static void main(String[] args) {
        int i, j, n;
        int sum, ans;
        Scanner input = new Scanner(System.in);

        while (true) {
            sum = 0;

            n = input.nextInt();
            a = new int[n + 1];
            b = new int[n + 1];
            T = new int[1000];

            for (i = 1; i <= n; i++) {
                a[i] = input.nextInt();
                sum += a[i];
            }
            for (i = 1; i <= n; i++) {
                b[i] = input.nextInt();
            }

            for (i = 1; i <= n; i++)
                for (j = sum; j >= 0; j--)
                    if (j >= a[i])
                        T[j] = MIN(T[j - a[i]], T[j] + b[i]);
                    else
                        T[j] = T[j] + b[i];

            ans = Integer.MAX_VALUE;
            for (j = 0; j <= sum; j++)
                ans = MIN(ans, MAX(j, T[j]));

            System.out.println(ans);
        }
    }

    private static int MAX(int a, int b) {
        return a > b ? a : b;
    }

    private static int MIN(int a, int b) {
        return a > b ? b : a;
    }
}

Input & Output

6
2 5 7 10 5 2
3 8 4 11 3 4
15

Reference

王晓东《计算机算法设计与分析》(第3版)P88

你可能感兴趣的:(Algorithm,动态规划,计算机算法设计与分析,Java,计算机算法设计与分析)