题目描述 

以下问题是模拟如何节省工料的约束优化问题,其中集合 A 是工料集合,集合B 是部
件集合,其中的数值代表工料和部件长度,问题是用集合 A 里面的工料生产集合B 里面的
部件,目标是节省工料:

输入文件为input.txt,共 4 行,第一行为A 的元素个数m,第 2 行为m 个值,用英文
逗号隔开,代表A 的元素,第 3 行为B 的元素个数n,第 4 行为n 个值,用英文逗号隔开,
代表B 的元素。m 和n 的最大值 20

例如输入文件:
4
3.5, 6, 9.2,10
3
1, 2, 4.5

输出文件为output.txt,共 n 行,每行 3 个值,其中第i 行的第一个值是B 里面第i 个
值,第二个值是一个索引值 j,表示将B 里面的第i 个值映射到A 的第j 个值,第三个值是A
里面的第j 个值的具体数值。i 和 j 的取值都是从 1 开始。每行的值用英文逗号隔开。

解题思路:

本题中我们需要找出所有满足A集合中符合大于B集合中各个元素,并且和最小的元素集合,值得注意的是,映射可以是一对一映射也可以是多对一,故可以将此问题抽象为CSP中的回溯搜索问题,采用最少剩余值(MRV)变量优先的方法:

  1. 首先对A和B集合进行排序,找出各个集合中剩余值最小的数(其中A集合剩余值最小的为4.5,B集合中剩余值最小的为6),进行第一轮计算。
  2. 将6减去4.5,剩余1.5,替代原B集合中的6,然后在A集合中找出符合的最大的数,发现是1,递归重复此步骤,得出0.5,发现没有符合的数。

此时重复上一步,得出2对应的值为3.5,答案为(1-6, 2-3.5, 4.5-6),所以y的值为6+3.5=9.5,从剩余值最小的往上遍历,重复以上步骤,遇到y的值更小的进行更新。

同时我也进行性能优化,在每次递归时从A集合剩余最小的元素,到刚好能满足B集合中所有元素之和的元素之间进行选择,减少了递归对比次数,对性能有一定的优化。

最后我们在读写文件时,要注意输入输出的格式、顺序。

本实验采取了CSP回溯问题中的最少剩余值(MRV)变量优先算法并给出了代码实现。在与几位同学交换测试用例后,也均能得出正确结论,可以验证此算法的正确性。虽然无法证明此算法为最优算法,但相较于暴力破解,还是做出了很多的优化,降低了部分的算法复杂度。

代码部分

首先创建一个工具类,用来保存答案。

import java.util.ArrayList;public class Result {private double y ;private ArrayList<ArrayList> resultArray;public  Result(){y = 0;resultArray = new ArrayList<>();}public double getY() {return y;}public void setY(double y) {this.y = y;}public ArrayList<ArrayList> getResultArray() {return resultArray;}public void setResultArray(ArrayList<ArrayList> result) {this.resultArray = result;}}

然后利用回溯法,进行求解。

private static void findMinY(ArrayList<Double> arrayA, ArrayList<Double> arrayB, Result resultTemp, Result result) {if(arrayA.size() == 0 || arrayB.size() == 0) {if(result.getY() == 0 ||result.getY() > resultTemp.getY()){result.setY(resultTemp.getY());result.setResultArray(resultTemp.getResultArray());resultTemp.setResultArray(new ArrayList<>());resultTemp.setY(0);return;}return;}int starIndex = 0, finalIndex = arrayA.size() - 1;while(starIndex < arrayA.size() - 1 && arrayA.get(starIndex) < arrayB.get(arrayB.size() - 1)){starIndex++;}if(starIndex >= arrayA.size()) starIndex--;double sumB = 0;for(int i = 0; i < arrayB.size(); i++){sumB = sumB + arrayB.get(i);}while(finalIndex > -1 && arrayA.get(finalIndex) > sumB){finalIndex--;}if(finalIndex < arrayA.size() - 1) finalIndex++;int middleIndex = starIndex;while(middleIndex >= starIndex && middleIndex <= finalIndex){double rest = arrayA.get(middleIndex) - arrayB.get(arrayB.size() - 1);ArrayList<Double> temp = new ArrayList<>();ArrayList<ArrayList> arrayTemp = resultTemp.getResultArray();double yTemp = resultTemp.getY();yTemp = yTemp + arrayA.get(middleIndex);resultTemp.setY(yTemp);temp.add(arrayB.get(arrayB.size() - 1));temp.add(arrayA.get(middleIndex));arrayTemp.add(temp);deleteArrayB.add(arrayB.get(arrayB.size() - 1));arrayB.remove(arrayB.size() - 1);for(int i = arrayB.size() - 1; i >= 0; i--){if(rest > arrayB.get(i)){ArrayList<Double> tempI = new ArrayList<>();tempI.add(arrayB.get(i));tempI.add(arrayA.get(middleIndex));arrayTemp.add(tempI);rest = rest - arrayB.get(i);deleteArrayB.add(arrayB.get(i));arrayB.remove(i);}}deleteArrayA.add(arrayA.get(middleIndex));arrayA.remove(middleIndex);resultTemp.setResultArray(arrayTemp);if((arrayB.size() == 0 && result.getY() == 0) || (arrayB.size() == 0 && result.getY() > resultTemp.getY())){result.setY(resultTemp.getY());result.setResultArray(resultTemp.getResultArray());resultTemp.setResultArray(new ArrayList<>());resultTemp.setY(0);return;}findMinY(arrayA, arrayB, resultTemp, result);middleIndex++;while(!deleteArrayA.isEmpty()){arrayA.add(deleteArrayA.remove(0));}Collections.sort(arrayA);while(!deleteArrayB.isEmpty()){arrayB.add(deleteArrayB.remove(0));}Collections.sort(arrayB);deleteArrayA.clear();deleteArrayB.clear();}return;}

主函数

import java.util.ArrayList;
import java.util.Arrays;
import java.io.*;
import java.util.Collections;public class ConstraintOptimization {/*** 查找排序后的数值在原数组中的索引位置* */public static int Seek(double[] arr, double number){for (int index = 0;index<arr.length;index++) {if (arr[index] == number) {//找到数值,返回索引return index;}}return -1;}/*** 读取txt文件*/public static ArrayList<String> readFile(String pathname) {ArrayList<String> input = new ArrayList<>();//防止文件建立或读取失败,用catch捕捉错误并打印,也可以throw;//不关闭文件会导致资源的泄露,读写文件都同理try (FileReader reader = new FileReader(pathname);BufferedReader br = new BufferedReader(reader) // 建立一个对象,它把文件内容转成计算机能读懂的语言) {String line;while ((line = br.readLine()) != null) {// 一次读入一行数据input.add(line);}} catch (IOException e) {e.printStackTrace();}return input;}/*** 写txt文件* */public static void writeFile(String writename, ArrayList<ArrayList> result) {try {File writeName = new File(writename);writeName.createNewFile(); // 创建新文件,有同名的文件的话直接覆盖try (FileWriter writer = new FileWriter(writeName);BufferedWriter out = new BufferedWriter(writer)) {for(int i = 0; i < result.size(); i++){String str = result.get(i).toString();out.write(str + "\r");}out.flush(); // 把缓存区内容写入文件}} catch (IOException e) {e.printStackTrace();}}/*** 进行约束优化 返回一个矩阵* */public static void Constraint_Optimization(double[] A, double[] B, Result result){double[] Asort =A.clone();//对A和B数组进行排序 方便找到最适合组件的原料Arrays.sort(Asort);double[] Bsort =B.clone();Arrays.sort(Bsort);ArrayList<Double> arrayA = toArraylist(Asort);ArrayList<Double> arrayB = toArraylist(Bsort);Result resultTemp = new Result();findMinY(arrayA,arrayB, resultTemp ,result);return;}static ArrayList<Double> deleteArrayA = new ArrayList<>();static ArrayList<Double> deleteArrayB = new ArrayList<>();private static void findMinY(ArrayList<Double> arrayA, ArrayList<Double> arrayB, Result resultTemp, Result result) {if(arrayA.size() == 0 || arrayB.size() == 0) {if(result.getY() == 0 ||result.getY() > resultTemp.getY()){result.setY(resultTemp.getY());result.setResultArray(resultTemp.getResultArray());resultTemp.setResultArray(new ArrayList<>());resultTemp.setY(0);return;}return;}int starIndex = 0, finalIndex = arrayA.size() - 1;while(starIndex < arrayA.size() - 1 && arrayA.get(starIndex) < arrayB.get(arrayB.size() - 1)){starIndex++;}if(starIndex >= arrayA.size()) starIndex--;double sumB = 0;for(int i = 0; i < arrayB.size(); i++){sumB = sumB + arrayB.get(i);}while(finalIndex > -1 && arrayA.get(finalIndex) > sumB){finalIndex--;}if(finalIndex < arrayA.size() - 1) finalIndex++;int middleIndex = starIndex;while(middleIndex >= starIndex && middleIndex <= finalIndex){double rest = arrayA.get(middleIndex) - arrayB.get(arrayB.size() - 1);ArrayList<Double> temp = new ArrayList<>();ArrayList<ArrayList> arrayTemp = resultTemp.getResultArray();double yTemp = resultTemp.getY();yTemp = yTemp + arrayA.get(middleIndex);resultTemp.setY(yTemp);temp.add(arrayB.get(arrayB.size() - 1));temp.add(arrayA.get(middleIndex));arrayTemp.add(temp);deleteArrayB.add(arrayB.get(arrayB.size() - 1));arrayB.remove(arrayB.size() - 1);for(int i = arrayB.size() - 1; i >= 0; i--){if(rest > arrayB.get(i)){ArrayList<Double> tempI = new ArrayList<>();tempI.add(arrayB.get(i));tempI.add(arrayA.get(middleIndex));arrayTemp.add(tempI);rest = rest - arrayB.get(i);deleteArrayB.add(arrayB.get(i));arrayB.remove(i);}}deleteArrayA.add(arrayA.get(middleIndex));arrayA.remove(middleIndex);resultTemp.setResultArray(arrayTemp);if((arrayB.size() == 0 && result.getY() == 0) || (arrayB.size() == 0 && result.getY() > resultTemp.getY())){result.setY(resultTemp.getY());result.setResultArray(resultTemp.getResultArray());resultTemp.setResultArray(new ArrayList<>());resultTemp.setY(0);return;}findMinY(arrayA, arrayB, resultTemp, result);middleIndex++;while(!deleteArrayA.isEmpty()){arrayA.add(deleteArrayA.remove(0));}Collections.sort(arrayA);while(!deleteArrayB.isEmpty()){arrayB.add(deleteArrayB.remove(0));}Collections.sort(arrayB);deleteArrayA.clear();deleteArrayB.clear();}return;}private static ArrayList<Double> toArraylist(double[] array) {ArrayList<Double> arraylist = new ArrayList<>();for(int i = 0; i < array.length; i++){arraylist.add(array[i]);}return arraylist;}/*** 将读取的文件数据流中的string 类型转化为题目所需的 double类型* */public static double[] StringToDouble(String[] string){double[] dou = new double[string.length];for(int i = 0; i < string.length; i++){dou[i] = Double.parseDouble(string[i]);}return dou;}/*** 主函数* */public static void main(String[] args){ArrayList<String> input = readFile("C:\\Users\\ricar\\Desktop\\input.txt");//合法性判断if(input.size() != 4){System.out.println("输入文件错误!请重新输入");return;}int n = Integer.parseInt(input.get(0));String[] Astring = new String[n];Astring = input.get(1).split(",");double[] A = StringToDouble(Astring);int m = Integer.parseInt(input.get(2));double[] B = StringToDouble(input.get(3).split(","));//进行合法性判断if(n != A.length || m != B.length){System.out.println(" 输入数组的个数错误 ");return;}Result result = new Result();Constraint_Optimization(A, B ,result);ArrayList<ArrayList> resultArray = seekIndex(result.getResultArray(), A, B);writeFile("C:\\Users\\ricar\\Desktop\\output.txt", resultArray);}private static ArrayList<ArrayList> seekIndex(ArrayList<ArrayList> resultArray, double[] a, double[] b) {ArrayList<ArrayList> result = new ArrayList<>();for(int i = 0; i < b.length; i++){for(int j = 0; j < resultArray.size(); j++){if(resultArray.get(j).get(0).equals(b[i])){ArrayList<Double> resultList = new ArrayList<>();resultList.add(b[i]);resultList.add((double) Seek(a, (Double) resultArray.get(j).get(1)));resultList.add((Double) resultArray.get(j).get(1));result.add(resultList);break;}}}return result;}
}

求解一个约束优化问题相关推荐

  1. 粒子群算法求解带约束优化问题 源码实现

    算法原理 之前求解的无约束的问题. 粒子群算法求解无约束优化问题 源码实现 算法原理如下 今天讲解下求解约束优化的问题.该问题常用的方法是罚函数法.即如果一个解x不满足约束条件,就对适应度值设置一个惩 ...

  2. 求解多变量非线性全局最优解_一种求解非线性约束优化全局最优的新方法

    一种求解非线性约束优化全局最优的新方法 刘子军,吕柏权,曹媛, (上海大学 机电工程与自动化学院  上海 200072) [摘要] 本文提出了一种求解非线性约束优化的全局最优的新方法-它是基于利用非线 ...

  3. 求解非约束优化问题的拟牛顿方法(BFGS、DFP)

    求解非约束优化问题的拟牛顿方法(BFGS.DFP) 拟牛顿法是一种以牛顿法为基础设计的,求解非线性方程组或连续的最优化问题函数的零点或极大.极小值的算法.当牛顿法中所要求计算的雅可比矩阵或Hessia ...

  4. Haskell语言实现求解一个整数所有因子的代码及运行结果

    问题: 求解一个整数的所有因子并输出 代码: factors::Int->[Int]factors n=[x|x<-[1..n],n`mod`x==0] 运行结果:

  5. 一阶矩+二阶矩估计求解一个参数

    一阶矩+二阶矩估计求解一个参数 @(概率论) 一般来说,一个参数对应一个方程.所以在矩估计法中,用一阶矩就可以求解一元.但是有些情况下,只写一阶矩,原理上是可以求得解的,但是,初等代数中很难剥离出来, ...

  6. 求解一个序列的最小相位序列

    求解一个序列的最小相位序列 什么是最小相位序列hmin(z) 一个例子 总结 例子说明 求解思路 零点搬移规律 由非最小相位系统构造全通系统和最小相位系统的过程原型 什么是最小相位序列hmin(z) ...

  7. 华为OD机试--求解一个连续递增数列,使得长度为k的数列之和为num

    给定一个整数num和一个数字k,求解一个连续递增数列,使得长度为k的数列之和为num,存在该数列时输出数列,不存在时输出-1 例如: 输入: 525 6 输出: 85 86 87 88 89 90 输 ...

  8. 简单题-不用库函数,求解一个数字的平方根

    题目: 如标题所示,不用平方根库函数,求解一个数字的平方根. 分析: 这个问题有两个思路: 思路1:采用二分的方式(无处不在的二分),上界初始化为数字本身,下界初始化为1,这样用二分,判断中间数字的平 ...

  9. 贪心算法求解一个序列中出现次数最多的元素问题

    贪心算法求解一个序列中出现次数最多的元素问题 题目: 指定n个正整数,编写一个实验程序找出它们中出现次数最多的数.如果这样的数有多个,请输出其中最小的一个. 输入描述:输入的第1行只有一个正整数n(1 ...

最新文章

  1. oracle触发器 条件,oracle触发器的定义和使用
  2. 生产交接班管理系统的安装设置并下载
  3. JavaScript Object对象
  4. 格式说明_现代诗歌的写作格式是什么,能否举例说明?
  5. php函数表达式,正规表达式函数_php
  6. 对话系统有哪些最新进展?这17篇EMNLP 2021论文给你答案
  7. [BZOJ1500][NOI2005]维修数列(splay)
  8. Android之GridView(九宫图)
  9. linux 取消证书登录密码,SUSELinux 中为 SSH 访问设置不输入密码的证书认证登录方式...
  10. 论坛头条内容链接地址有误
  11. 智能家居至今未落地 究其原因是没想好怎么分蛋糕
  12. 疯狂Java讲义P179单例
  13. Excel学习笔记 - 单元格的引用
  14. 《Java解惑》系列——02字符谜题——谜题11:最后的笑声(字符、字符串连接操作)
  15. 基因加性方差、显性方差与上位性方差定义
  16. 算法设计与分析之分治法
  17. 学习英语02——词汇——01
  18. Win7下的Linux通过Nat的VMnet8下的NAT方式进行上网
  19. Vue的created的使用示例
  20. 这款TWS蓝牙耳机颜值与实用性到底怎么样?

热门文章

  1. 生成对抗网络——GAN(一)
  2. stata里reghdfe函数在不同固定效应设计下的观测值问题
  3. WEB阶段7:综合练习-联系人管理系统-增删改查查询分页
  4. vue前端实现从数据库获取数据的下拉框以及带参请求
  5. 【转】为什么很多看起来不是很复杂的网站,比如 Facebook、淘宝,都需要大量顶尖高手来开发?...
  6. 智能合约开发——TypeScript 基础(全)
  7. FFmpeg m3u8文件返回Invalid data found when processing input错误
  8. 【C语言】全面解析指针,指针知识点整理
  9. 【​观察】全面屏手机战役的背后 差异化创新还是同质化加速?
  10. 必应每日壁纸API HTML 使用必应每日API为背景 css 背景图片 加模糊 遮罩