算法设计与分析: 3-28 m处理器问题

3-28 m处理器问题


问题描述

在一个网络通信系统中,要将 n 个数据包依次分配给 m 个处理器进行数据处理,并要求处理器负载尽可能均衡。
设给定的数据包序列为: { σ 0 , σ 1 , . . . , σ n 1 }
m处理器问题要求的是 r 0 = 0 r 1 . . . r m 1 n = r m ,将数据包序列划分为m段: { σ 0 , . . . , σ r 1 1 } , { σ r 1 , . . . , σ r 2 1 } , … , { σ r m 1 , . . . , σ n 1 } , 使 max i = 0 m 1 f ( r i , r i + 1 ) 达到最小。式中, f ( i , j ) = σ i 2 + . . . + σ j 2 是序列 { σ i , . . . , σ j } 的负载量。
max i = 0 m 1 f ( r 1 , r i + 1 ) 的最小值称为数据包序列 { σ 0 , σ 1 , . . . , σ n 1 } 的均衡负载量。

对于给定的数据包序列 { σ 0 , σ 1 , . . . , σ n 1 } ,编程计算 m 个处理器的均衡负载量。

数据输入:
第 1 行有 2 个正整数 n 和 m。n 表示数据包个数,m 表示处理器数。接下来的 1 行中有 n 个整数,表示 n 个数据包的大小。


Java: version 1

import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.Scanner;

public class MChuLiQi {

    private static int n,m;
    private static double[][] g;
    private static int MAX = 1000000;
    private static int[] packets;

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

        while (true){
            n = input.nextInt();
            m = input.nextInt();

            g = new double[n+1][m+1];
            packets = new int[n];

            for(int i=0; i<n; i++){
                packets[i] = input.nextInt();
            }

            solution();

            DecimalFormat formater = new DecimalFormat("#0.##");
            formater.setRoundingMode(RoundingMode.FLOOR);
            System.out.println(formater.format(g[0][m]));
        }
    }

    private static void solution(){
        int i,j,k;
        double tmp,maxt;
        tmp = f(n-1,n-1);
        for(i=n-1; i>=0; i--){
            if(f(i,i) > tmp)
                tmp = f(i,i);
            g[i][1] = f(i,n-1);
            if(n-i <= m)
                g[i][n-i] = tmp;
        }
        for(i=n-1; i>=0; i--){
            for(k=2; k<=m; k++){
                for(j=i,tmp=MAX; j<=n-k; j++){
                    maxt = max(f(i,j),g[j+1][k-1]);
                    if(tmp > maxt)
                        tmp = maxt;
                }
                g[i][k] = tmp;
            }
            for(k=n-i+1; k<=m; k++)
                g[i][k] = g[i][n-i];
        }
    }

    private static double f(int i, int j){
        double sum = 0;
        if(i == j)
            return Math.sqrt(Math.pow(packets[i],2));
        else
            for(int k=i; k<=j; k++){
                sum += Math.pow(packets[k],2);
            }
            return Math.sqrt(sum);
    }

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

Java: version 2

import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.Scanner;

public class MChuLiQi1 {

    private static int n,m;
    private static double[][] g;
    private static int[] packets;

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

        while (true){
            n = input.nextInt();
            m = input.nextInt();

            g = new double[n+1][m+1];
            packets = new int[n];

            for(int i=0; i<n; i++){
                packets[i] = input.nextInt();
            }

            solution();

            DecimalFormat formater = new DecimalFormat("#0.##");
            formater.setRoundingMode(RoundingMode.FLOOR);
            System.out.println(formater.format(g[0][m]));
        }
    }

    private static void solution(){
        int i,j,k;
        for(i=n-1; i>=0; i--)
            g[i][1] = f(i,n-1);

        for(k=2; k<=m; k++){
            g[n-k][k] = max(f(n-k,n-k), g[n-k+1][k-1]);
            j = n-k;
            for(i=n-k-1; i>=m-k; i--){
                if(f(i,j) <= g[j+1][k-1])
                    g[i][k] = g[j+1][k-1];
                else
                    if(f(i,i) >= g[i+1][k-1]){
                        g[i][k] = f(i,i);
                        j = i;
                    }
                    else{
                        while (f(i,j-1) >= g[j][k-1])
                            j--;
                        g[i][k] = min(f(i,j), g[j][k-1]);
                        if(g[i][k] == g[j][k-1])
                            j--;
                    }
            }
        }
    }

    private static double f(int i, int j){
        double sum = 0;
        if(i == j)
            return Math.sqrt(Math.pow(packets[i],2));
        else
            for(int k=i; k<=j; k++){
                sum += Math.pow(packets[k],2);
            }
        return Math.sqrt(sum);
    }

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

    private static double min(double a, double b){
        return a > b ? b : a;
    }
}

Input & Output

6 3 
2 2 12 3 6 11
12.32

Reference

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

猜你喜欢

转载自blog.csdn.net/ioio_/article/details/81051519