算法设计与分析: 4-14 嵌套箱问题

4-14 嵌套箱问题


问题描述

一个d维箱 ( x 1 , x 2 , . . . , x d ) 嵌入另一个d维箱 ( y 1 , y 2 , . . . , y d ) 是指存在 1 , 2 , . . . , d 的一个 排列 π ,使得 x π ( 1 ) < y 1 , x π ( 2 ) < y 2 , . . . , x π ( d ) < y d
(1)证明上述箱嵌套关系具有传递性;
(2)试设计一个有效算法,用于确定一个 d 维箱是否可嵌入另一个 d 维箱;
(3)给定由 n 个 d 维箱组成的集合 { B 1 , B 2 , . . . , B n } ,试设计一个有效算法找出这 n 个 d维箱中的一个最长嵌套箱序列,并用 n 和 d 描述算法的计算时间复杂性。

给定由 n 个 d 维箱,试设计一个有效算法,找出这 n 个 d 维箱中的一个最长嵌套箱序列。

数据输入:
含多个测试项。每个测试数据项的第一行中有 2 个整数 n 和 d,分别表示箱的个数和维数。其后 n 行每行有 d 个正整数,表示箱的各维的长度。


Java

import java.util.Arrays;
import java.util.Scanner;

public class QianTaoXiang {

    private static int MAX = 50;
    private static int[][] box = new int[MAX][MAX];
    private static int[][] a = new int[MAX][MAX];   //a[i][n]表示i的高度,如i嵌套j,a[i][j]=1
    private static int[] x = new int[MAX];  //最长嵌套箱序列
    private static int n, d;

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

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

            int i, j;
            for (i = 0; i < n; i++) {
                for (j = 0; j < d; j++) {
                    box[i][j] = input.nextInt();
                }
            }

            int count = load();
            System.out.println();
            System.out.println("最长嵌套箱序列长度为: " + count);
            System.out.print("最长嵌套箱序列为: ");
            for (i = count - 1; i >= 0; i--)
                System.out.print(x[i] + 1 + " ");
        }
    }

    //如果i嵌入j,返回1,如果j嵌入i,返回-1,如无嵌套关系,返回0
    private static int nest(int i, int j) {
        //将各维度排序
        Arrays.sort(box[i], 0, d);
        Arrays.sort(box[j], 0, d);

        int l;
        if (box[i][0] < box[j][0]) {
            for (l = 1; l < d; l++)
                if (box[i][l] >= box[j][l])
                    return 0;
            return 1;
        } else {
            for (l = 1; l < d; l++)
                if (box[i][l] <= box[j][l])
                    return 0;
            return -1;
        }
    }

    //递归修改嵌套箱深度值
    //i嵌入j
    private static void addHeight(int i, int j) {
        if (a[i][n] == a[j][n]) { //如果i与j的深度相同
            a[j][n]++;
        }
        int k;
        for (k = 0; k < n; k++)
            if (a[j][k] == 1)  //j嵌入k
                addHeight(j, k); //k的高度增加
    }

    //寻找最大深度的箱子作为首嵌套箱
    private static int findMax() {
        int i;
        int max = a[0][n];
        int maxIndex = 0;
        for (i = 1; i < n; i++)
            if (a[i][n] > max) {
                max = a[i][n];
                maxIndex = i;
            }
        return maxIndex;
    }

    //输出最长嵌套箱序列
    private static int trace(int maxIndex) {
        int m;
        int count = 0;
        int index = maxIndex;
        int i;
        x[count++] = index;
        int temp = 0;
        while (a[index][n] > 0) {
            m = 0;
            for (i = 0; i < n; i++)
                if (a[i][index] == 1 && a[i][n] >= m) //如果i嵌入index,且i的高度最高
                {
                    m = a[i][n];
                    temp = i;
                }
            index = temp;
            x[count++] = index;
        }
        return count--;
    }

    //计算嵌套关系,结点高度
    private static int load() {
        //计算嵌套关系
        int i, j;
        for (i = 0; i < n; i++)
            for (j = 0; j < n; j++)
                a[i][j] = nest(i, j);

        //递归修改嵌套深度
        for (i = 0; i < n; i++)
            for (j = 0; j < n; j++)
                if (a[i][j] == 1)  //如果i嵌入j
                    addHeight(i, j);  //增加j的高度

        //寻找最大深度的箱子作为首嵌套箱
        int maxIndex = findMax();

        //输出最长嵌套箱序列
        return trace(maxIndex);
    }
}

Input & Output

5 2
3 7
8 10
5 2
9 11
21 18
8 6
5 2 20 1 30 10
23 15 7 9 11 3
40 50 34 24 14 4
9 10 11 12 13 14
31 4 18 8 27 17
44 32 13 19 41 19
1 2 3 4 5 6
80 37 47 18 21 9
最长嵌套箱序列长度为: 5
最长嵌套箱序列为: 3 1 2 4 5 

最长嵌套箱序列长度为: 4
最长嵌套箱序列为: 7 2 5 6 

Reference

王晓东《计算机算法设计与分析》
https://blog.csdn.net/u012319493/article/details/50009441

猜你喜欢

转载自blog.csdn.net/IOIO_/article/details/81069918