这几天室友过了荣耀的机试,听他说有个小蜜蜂采蜜的问题,想着记录一下。
我们采用的是暴力解法,即求出所有的采蜜顺序,并求解距离。求采蜜顺序其实是一个求解全排列的过程,这里要谢谢这位本家人的全排列代码地址。最后附上全部代码。` private List<List> res = new ArrayList<>();
//声明一个布尔数组,用来判断某个索引位置的数字是否被使用过了
private boolean[] used;
public void permute(int[] actual) {
/**小蜜蜂采蜜
*action为坐标数组
*/
//先根据坐标数组得到一个新数组(用来求全排列),里面的元素是从1到action.length/2
int[] nums = new int[actual.length / 2];
for (int i = 1; i <= actual.length / 2; i++) {
nums[i - 1] = i;
}
used = new boolean[nums.length];
List<Integer> preList = new ArrayList<>();
generatePermutation(nums, 0, preList);
//存储最小距离
double min_distance = Double.MAX_VALUE;
//存储最小距离对应的采蜜顺序
List<Integer> min_queue= null;
//根据全排列的结果来取对应的坐标 并计算距离
for (int i = 0; i < res.size(); i++) {
int firstindex = res.get(i).get(0);
int x_x = actual[2 * (firstindex - 1)] * actual[2 * (firstindex - 1)];
int y_y = actual[2 * (firstindex - 1) + 1] * actual[2 * (firstindex - 1) + 1];
double distance = Math.sqrt(x_x + y_y);
for (int j = 1; j < res.get(i).size(); j++) {
int index = res.get(i).get(j);
int pre_index = res.get(i).get(j - 1);
int x_cha = (actual[2 * (index - 1)] - actual[2 * (pre_index - 1)]) * (actual[2 * (index - 1)] - actual[2 * (pre_index - 1)]);
int y_cha = (actual[2 * (index - 1) + 1] - actual[2 * (pre_index - 1) + 1]) * (actual[2 * (index - 1) + 1] - actual[2 * (pre_index - 1) + 1]);
distance += Math.sqrt(x_cha + y_cha);
}
System.out.println(res.get(i));
System.out.println(distance);
if(distance<min_distance){
min_distance=distance;
min_queue=res.get(i);
}
}
System.out.println("最小的顺序是"+min_queue);
System.out.println("最小距离是"+min_distance);
}
private void generatePermutation(int[] nums, int index, List<Integer> preList) {
/**
* 回溯
*求全排列
* @param nums 给定数组
* @param index 当前考察的索引位置
* @param preList 先前排列好的子序列
*/
//index 等于给定数组的长度时,说明一种排列已经形成,直接将其加入成员变量 res 里
if (index == nums.length) {
//这里需要注意java的值传递
//此处必须使用重新创建对象的形式,否则 res 列表中存放的都是同一个引用
res.add(new ArrayList<>(preList));
return;
}
for (int i = 0; i < nums.length; i++) {
if (!used[i]) {
preList.add(nums[i]);
used[i] = true;
generatePermutation(nums, index + 1, preList);
//一定要记得回溯状态
preList.remove(preList.size() - 1);
used[i] = false;
}
}
return;
}`