生成最佳的配料配置算法

来源:互联网 发布:马思纯长相知乎 编辑:程序博客网 时间:2024/04/27 13:54

 1.题目

求解数学题目,题目的背景:求最佳的优化分配,即在一个烧煤厂中有很多配料,每个配料有不同的成分(如含碳10%,含水20%,含镁30%。。。)。共有配料15种左右,每种配料含量在0——100个单位之间。最后汇总后,每种成份的总含量都有范围限定(如总含碳量在15%到20%之间。。。)。求最优解(每种配料价格不同,最后求出总价最低的解法)。

 2.计算后效果

只需配置一个文本文件,把各个配料的价格、最大、最小比例、名称等信息填进去,运行我的程序,就可以弹出一个对话框,显示各个配料的最佳比例的详细信息,包括该比例下的总价格以及各个配料的配置比例。 该程序还可以检查进行异常检查,在最大比例是否大于对小比例、最小比例之和大于100%,最大比例之和小于100%的情况下提示异常信息。

 

 

3.使用方法

根据需要修改如下配置信息:

[SourceType]
TotalNum = 10

[Source1]
SourceName = Source01
SourceContanPerMax = 30
SourceContanPerMin = 15
Price = 30

[Source2]
SourceName = Source02
SourceContanPerMax = 30
SourceContanPerMin = 1
Price = 10

[Source3]
SourceName = Source03
SourceContanPerMax = 30
SourceContanPerMin = 15
Price = 10

[Source4]
SourceName = Source04
SourceContanPerMax = 30
SourceContanPerMin = 15
Price = 100

[Source5]
SourceName = Source05
SourceContanPerMax = 30
SourceContanPerMin = 15
Price = 10

[Source6]
SourceName = Source06
SourceContanPerMax = 30
SourceContanPerMin = 15
Price = 8

[Source7]
SourceName = Source07
SourceContanPerMax = 30
SourceContanPerMin = 3
Price = 5

[Source8]
SourceName = Source08
SourceContanPerMax = 30
SourceContanPerMin = 2
Price = 10

[Source9]
SourceName = Source09
SourceContanPerMax = 20
SourceContanPerMin = 2
Price = 1

[Source10]
SourceName = Source10
SourceContanPerMax = 30
SourceContanPerMin = 2
Price = 8

[Source11]
SourceName = Source11
SourceContanPerMax = 30
SourceContanPerMin = 2
Price = 30

 4.算法实现

public class Source {
    public String SourceName = "";
    public int MaxPer = 0;
    public int MinPer = 0;
   
    public int Price = 0;
   
    public int usedPercent = 0;
}

public class MixJudger {

 /** 配置文件名 */
 private static final String strFileName = "data/config.ini";
 
 public static void main(String[] args) {
  String strSectionName = "SourceType";
  String strKeyName = "TotalNum";
  String strSourTypeNum = "";
  int nSourTypeNum = 0;
  HashMap hmSource = new HashMap();
  
  try {
   strSourTypeNum = ProfileStringMgr.getInstace().getProfileString(strFileName, strSectionName, strKeyName, "0");
   nSourTypeNum = Integer.parseInt(strSourTypeNum);
   String tempSection = "";
   //String tempKey = "";
   String tempValue = "";
   
   for(int i = 0; i < nSourTypeNum; i++){
    Source tmpSur = new Source();
    
    strSectionName = "Source" + String.valueOf(i + 1);
    
    strKeyName = "SourceName";
    tempValue = ProfileStringMgr.getInstace().getProfileString(strFileName, strSectionName, strKeyName, "0");
    tmpSur.SourceName = tempValue;
    
    //
    strKeyName = "SourceContanPerMax";
    tempValue = ProfileStringMgr.getInstace().getProfileString(strFileName, strSectionName, strKeyName, "0");
    tmpSur.MaxPer = Integer.parseInt(tempValue);
    
    strKeyName = "SourceContanPerMin";
    tempValue = ProfileStringMgr.getInstace().getProfileString(strFileName, strSectionName, strKeyName, "0");
    tmpSur.MinPer = Integer.parseInt(tempValue);
    
    strKeyName = "Price";
    tempValue = ProfileStringMgr.getInstace().getProfileString(strFileName, strSectionName, strKeyName, "0");
    tmpSur.Price = Integer.parseInt(tempValue);
    
    hmSource.put(i, tmpSur);
   }
   
   int SouceNum = hmSource.size();
   int totalPercent = 0;
   
   // 限定配料的个数
   if(SouceNum > 10){
    JOptionPane.showMessageDialog(null, "对不起该演示版本的配料个数不能超过10个",
         "占海提示", JOptionPane.INFORMATION_MESSAGE);
    return;
   }
   
   // 检查下最大值是否都大于最小值,不然报错
   for (int i = 0; i < SouceNum; i++){
    Source tmpSur = (Source) hmSource.get(i);
    if(tmpSur.MaxPer < tmpSur.MinPer){
     JOptionPane.showMessageDialog(null, "配料名:" + tmpSur.SourceName + "的最大比例之小于最小比例,请检查数据是否正确",
          "占海提示", JOptionPane.INFORMATION_MESSAGE);
     return;
    }
   }
   
   
   // 检查下如果都取最大会不会不到100%
   for (int i = 0; i < SouceNum; i++){
    Source tmpSur = (Source) hmSource.get(i);
    totalPercent = totalPercent + tmpSur.MaxPer;
   }
   
            if(totalPercent < 100){
             JOptionPane.showMessageDialog(null, "各个配料的最大比例之和仍小于100%,请检查数据是否正确",
         "占海提示", JOptionPane.INFORMATION_MESSAGE);
             return;
   }
   
   // 先获得最小percent
            totalPercent = 0;
   for (int i = 0; i < SouceNum; i++){
    Source tmpSur = (Source) hmSource.get(i);
    totalPercent = totalPercent + tmpSur.MinPer;
    tmpSur.usedPercent = tmpSur.MinPer;
    hmSource.put(i, tmpSur);
   }
   
            if(totalPercent > 100){
             JOptionPane.showMessageDialog(null, "各个配料的最小比例之和已大于100%,请检查数据是否正确",
         "占海提示", JOptionPane.INFORMATION_MESSAGE);
             return;
   }
   
   // 开始计算
            while(totalPercent < 100){
             // 遍历一遍找到价格最少的配料
             int minPrice = 100000000;
             int minPirceIndex = 0;
             for (int i = 0; i < SouceNum; i++){
        Source tmpSur = (Source) hmSource.get(i);
                    if(tmpSur.usedPercent == tmpSur.MaxPer){
                     continue;
                    }
                    if(minPrice > tmpSur.Price){
                     minPrice = tmpSur.Price;
                     minPirceIndex = i;
                    }
       }
             
             // 进行更新比例
             Source tmpSur = (Source) hmSource.get(minPirceIndex);
             tmpSur.usedPercent++;
             totalPercent++;
             hmSource.put(minPirceIndex, tmpSur);
            }
           
            // 计算出总钱数
            int totalMoney = 0;
            for (int i = 0; i < SouceNum; i++){
    Source tmpSur = (Source) hmSource.get(i);
    totalMoney = totalMoney + tmpSur.usedPercent + tmpSur.Price;
   }
           
           
            // 显示的详细信息
            StringBuffer sb = new StringBuffer();
            sb.append("各个配料的总钱数为" + totalMoney).append(", 详细信息如下:").append("\n");
            for (int i = 0; i < SouceNum; i++){
    Source tmpSur = (Source) hmSource.get(i);
    sb.append("配料名称:").append(tmpSur.SourceName).append("使用比例:").append(tmpSur.usedPercent).append(",单价:").append(tmpSur.Price).append("\n");
    
    totalMoney = totalMoney + tmpSur.usedPercent + tmpSur.Price;
   }
           
            System.out.print(sb.toString());
            JOptionPane.showMessageDialog(null, sb.toString(),
     "占海提示", JOptionPane.INFORMATION_MESSAGE);
  
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }
}

 

 

原创粉丝点击