算法设计与分析: 5-2 最小长度电路板排列问题

5-2 最小长度电路板排列问题


问题描述

最小长度电路板排列问题是大规模电子系统设计中提出的实际问题。该问题的提法是,将 n 块电路板以最佳排列方案插入带有 n 个插槽的机箱中。n 块电路板的不同的排列方式对 应于不同的电路板插入方案。
B = { 1 2 . . . n } 是n块电路板的集合。集合 L = { N 1 N 2 . . . N m } 是n块电路
板的 m 个连接块。其中每个连接块 N i 是 B 的一个子集,且 N i 中的电路板用同一根导线连接在一起。
例如,设 n=8,m=5。给定 n 块电路板及其 m 个连接块如下: B = { 1 2 3 4 5 6 7 8 } ; L = { N 1 N 2 N 3 N 4 N 5 } ;
N 1 = { 4 5 6 } ; N 2 = { 2 3 } ; N 3 = { 1 3 } ; N 4 = { 3 6 } ; N 5 = { 7 8 } 。 这 8 块电路板的一个可能的排列如图所示。
最小长度电路板排列问题

在最小长度电路板排列问题中,连接块的长度是指该连接块中第 1 块电路板到最后 1 块电路板之间的距离。例如在图示的电路板排列中,连接块 N 4 的第 1 块电路板在插槽 3 中, 它的最后 1 块电路板在插槽 6 中,因此 N 4 的长度为 3。同理 N 2 的长度为 2。图中连接块最大长度为 3。试设计一个回溯法找出所给 n 个电路板的最佳排列,使得 m 个连接块中最大长 度达到最小。

对于给定的电路板连接块,设计一个算法,找出所给 n 个电路板的最佳排列,使得 m 个连接块中最大长度达到最小。

数据输入:
第一行有 2 个正整数 n 和 m (1≤m,n≤20)。接下来的 n 行中,每行有 m 个数。第 k 行的第 j 个数为 0 表示电路板 k 不在连接块 j 中,1 表示电路板 k 在连接块 j 中。


Java

package Chapter5HuiSuFa;

import java.util.Scanner;

public class ZuiXiaoChangDuDianLuBanPaiLie {

    private static int n,m;
    private static int[] bestx;
    private static int[][] B;

    private static int[] x,low,high;
    private static int bestd;

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

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

            bestx = new int[n+1];
            B = new int[n+1][m+1];

            for(int i=1; i<=n; i++)
                for(int j=1; j<=m; j++)
                    B[i][j] = input.nextInt();

            int minLen = arrangeBoards();

            System.out.println(minLen);

            for(int i=1; i<=n; i++)
                System.out.print(bestx[i]+" ");
        }
    }

    private static int arrangeBoards(){
        x = new int[n+1];
        low = new int[m+1];
        high = new int[m+1];

        bestd = n+1;

        for(int i=1; i<=n; i++)
            x[i] = i;

        backtrack(1);

        return bestd;
    }

    private static void backtrack(int i){
        if(i == n){
            int tmp = len(i);
            if(tmp < bestd){
                bestd = tmp;
                for(int j=1; j<=n; j++)
                    bestx[j] = x[j];
            }
        }else{
            for(int j=i; j<=n; j++){
                swap(x,i,j);
                int ld = len(i);
                if(ld < bestd)
                    backtrack(i+1);
                swap(x,i,j);
            }
        }
    }

    private static int len(int ii){
        for(int i=1; i<=m; i++){
            high[i] = 0;
            low[i] = n+1;
        }
        for(int i=1; i<=ii; i++)
            for(int k=1; k<=m; k++)
                if(B[x[i]][k] > 0){
                    if(i < low[k]) low[k] = i;
                    if(i > high[k]) high[k] = i;
                }
        int tmp = 0;
        for(int k=1; k<=m; k++)
            if(low[k]<=n && high[k]>0 && tmp<high[k]-low[k])
                tmp = high[k] - low[k];

        return tmp;
    }

    private static void swap(int[] x, int i, int j){
        int tmp;
        tmp = x[i];
        x[i] = x[j];
        x[j] = tmp;
    }
}

Input & Output

8 5
1 1 1 1 1
0 1 0 1 0
0 1 1 1 0
1 0 1 1 0
1 0 1 0 0
1 1 0 1 0
0 0 0 0 1
0 1 0 0 1
4
5 4 3 1 6 2 8 7 

Reference

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

猜你喜欢

转载自blog.csdn.net/ioio_/article/details/81092077
今日推荐