算法设计与分析: 5-34 排列树问题

5-34 排列树问题


问题描述

试设计一个用回溯法搜索排列空间树的函数。该函数的参数包括结点可行性判定函数和上界函数等必要的函数,并将此函数用于解圆排列问题。
圆排列问题描述如下:给定 n 个大小不等的圆 c 1 , c 2 , . . . , c n ,现要将这 n 个圆排进一个矩形框中,且要求各圆与矩形框的底边相切。圆排列问题要求从 n 个圆的所有排列中找出有最小长度的圆排列。
例如,当 n=3,且所给的 3 个圆的半径分别为 1,1,2 时,这 3 个圆的最小长度的圆排 列如图所示,其最小长度为 2 + 4 2

排列树圆排列

对于给定的 n 个圆,编程计算最小长度排列。

数据输入:
第 1 行是 1 个正整数 n,表示有 n 个圆。第 2 行有 n 个正数,分别表示 n 个圆的半径。


Java

package Chapter5HuiSuFa;

import java.util.Scanner;

public class PaiLieShu {

    private static int MAX = 100000;
    private static int n;
    private static float min,centerx;
    private static float[] x,xr;

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

        while (true){
            min = MAX;

            n = input.nextInt();

            x = new float[n+1];
            xr = new float[n+1];

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

            backtrack(1);

            output();
        }
    }

    private static void backtrack(int t){
        if(t > n) record();
        else
            for(int i=t; i<=n; i++){
                swap(x,t,i);
                if(constraint(t) && bound(t)){
                    change(t);
                    backtrack(t+1);
                    restore(t);
                }
                swap(x,t,i);
            }
    }

    private static void swap(float[] x, int m, int n){
        float tmp = x[m];
        x[m] = x[n];
        x[n] = tmp;
    }

    private static void record(){
        float low=0,high=0;
        for(int i=1; i<=n; i++){
            if(xr[i]-x[i] < low) low=xr[i]-x[i];
            if(xr[i]+x[i] > high) high=xr[i]+x[i];
        }
        if(high-low < min) min=high-low;
    }

    private static boolean constraint(int t){
        return true;
    }

    private static boolean bound(int t){
        centerx = center(t);
        if(centerx+x[t]+x[1] < min) return true;
        else return false;
    }

    private static void change(int t){
        xr[t] = centerx;
    }

    private static void restore(int t){
    }

    private static float center(int t){
        float temp = 0;
        for(int j=1; j<t; j++){
            float valuex = (float) (xr[j]+2.0*Math.sqrt(x[t]*x[j]));
            if(valuex > temp) temp=valuex;
        }

        return temp;
    }

    private static void output(){
        System.out.println(String.format("%.5f",min));
    }
}

Input & Output

3
1 1 2
7.65685


9
17 49 77 84 86 64 75 88 65 
1159.66772

Reference

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

猜你喜欢

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