打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
算法设计与分析 5.10 圆排列问题

/***********************************************************
 *                  5.10 圆排列问题
 * 1.问题描述
 * 给定 n 个大小不等的圆 c1, c2, c3, ..., cn, 现在要将这 n 个圆排进
 * 一个矩形框中,且要求各圆与矩形框的底边相切。圆排列问题要求从 n 个圆的
 * 所有排列中找出有最小长度的圆排列。
 *
 * 2.算法设计
 * 圆排列问题的解空间是一棵排列树。按照回溯法搜索排列树的算法框架,设开始
 * 时 a = [r1, r2, ..., rn] 是所给的 n 个圆的半径,则相应的排列树由
 * a[1, .., n] 的所有排列构成。
 *
 * 3.复杂度
 * O(n!)
 */
public class Circles {
 static int n;   //待排列的圆的个数
 static float min;  //当前最优值
 static float[] x;  //当前圆排列圆心横坐标
 static float[] r;  //当前圆排列
 
 public static float circlePerm(int nn, float[] rr) {
  n = nn;
  min = Float.MAX_VALUE;
  x = new float[n];
  r = rr;
  trackback(0);
  return min;
 }

 private static void trackback(int t) {
  if (t == n - 1) {
   compute();
  } else {
   for (int j = t; j < n; j++) {
    swap(r, t, j);
    float centerx = center(t);
    if (centerx + r[t] + r[0] < min) { //下界约束
     x[t] = centerx;
     trackback(t + 1);
    }
    swap(r, t, j);
   }
  }
  
 }

 private static float center(int t) {
  //计算当前所选择圆的圆心横坐标
  float temp = 0;
  for (int j = 1; j < t; j++) {
   float valuex = (float)(x[j] + 2.0 * Math.sqrt(r[t] * r[j]));
   if (valuex > temp) {
    temp = valuex;
   }
  }
  return temp;
 }

 private static void compute() {
  // 计算当前圆排列的长度
  float low = 0;
  float high = 0;
  for (int i = 0; i < n; i++) {
   if (x[i] - r[i] < low)
    low = x[i] - r[i];
   if (x[i] + r[i] > high)
    high = x[i] + r[i];
  }
  if (high - low < min)
   min = high - low;  
 }
 
 private static void swap(float[] array, int i, int j) {
  float temp = array[i];
  array[i] = array[j];
  array[j] = temp;
 }
}
 

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
在顺序存储模式下的三种算法
在Java数组中将数组中的奇数置后偶数置前(两种不同的方法实现)
贪心算法在背包中的应用—编程爱好者网站 http://www.programfan.com
C语言数组名作函数参数
C语言学习——指针精华(1)
OpenCV-图像明度
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服