バックパック問題解決会社のスナック購入(貪欲+バブリング+ダイナミック)

  • 問題の説明
    • 会社はスナックを購入する必要があるため、数量が限られている場合、スナックの種類や数量の選び方が毎回検討する必要のある問題になっていますので、自動でスナック購入リストを生成して保存できるプログラムがあります会社は購入が難しい女性を選びます。
    • 入力:スナックの名前の配列、対応する単価、スナックの好みの配列、および合計金額。
    • 出力:スナックの好みを考慮して、できるだけ予算を使い、購入したスナックの種類、購入金額、および実際のコストを出力します。
  • ソースコードスナック購入配布
  • 入力パラメータ
/**
* @params foodName 零食名称
* @params prices   零食价格
* @params lover    零食喜好度(用于调节零食选择的偏好参数,此处表示受欢迎程度)
* @params sumMoney 总预算
*/
String[] foodName = {
    
    "小当家", "牛肉干", "饼干", "香肠", "面包", "麻花", "蛋糕", "麻薯", "桂花饼", "玉米粒", "猪肉干"};
double[] prices = {
    
    2.2, 5.8, 1.3, 1.0, 4.7, 1.12, 5.6, 4.5, 6.6, 2.3, 5.4};
double[] lover01 = {
    
    4.1, 7.2, 3.3, 5.4, 2.6, 1.1, 6.9, 3.8, 6.7, 4.5, 6.9};
int sumMoney01 = 10;
int sumMoney02 = 30;
int sumMoney03 = 60;
int sumMoney04 = 90;
int sumMoney05 = 140;
  • 結果を示す
公司预算:10
实际花费:10.0
选取的零食种类:
小当家*2 玉米粒*1 饼干*1 香肠*2 

公司预算:30
实际花费:29.120000000000005
选取的零食种类:
小当家*1 桂花饼*1 牛肉干*1 猪肉干*1 玉米粒*1 蛋糕*1 饼干*1 香肠*1 麻花*1 

公司预算:60
实际花费:58.319999999999986
选取的零食种类:
小当家*6 桂花饼*7 牛肉干*7 猪肉干*7 玉米粒*7 蛋糕*6 饼干*6 香肠*6 麻花*6 麻薯*1 

公司预算:90
实际花费:88.91999999999999
选取的零食种类:
小当家*11 桂花饼*11 牛肉干*12 猪肉干*12 玉米粒*11 蛋糕*12 面包*1 饼干*11 香肠*11 麻花*11 麻薯*12 

公司预算:140
实际花费:138.4000000000001
选取的零食种类:
小当家*20 桂花饼*20 牛肉干*21 猪肉干*21 玉米粒*20 蛋糕*21 面包*21 饼干*20 香肠*20 麻花*20 麻薯*21 
  • 問題解決のアイデア

    • 1つ目は、「貪欲率=スナックの好み/スナックの価格」に従ってスナックを並べ替えることです。この比率は、スナックの価格が高いほど人気が​​高く、スナックの価格が低いほど、購入できる数が多いことを示します。
    • 選別はバブリングを利用しており、貪欲率、スナック価格、スナック名の選別を考えると、バブリング、選別、挿入が一般的に考えられ、なるべく高速な選別は避けるべきである。
    • 貪欲率に基づいて食品を選択する場合は、貪欲率が上部にあるk個の食品のみを設定します。各食品の数量は、num =合計価格/(X1 + X2 + X3 + X4 +…+ Xk)です。
    • 次に、残りのmaintain_money =合計金額*価格(X1 + X2 + X3 + X4 +…+ Xk);
    • ここで制御できる変数は、トップよりも貪欲なk個の食品とnumです。必要なkとnumを設定できます。
    • 最後に、残りの食品、食品価格、​​remain_moneyの動的計画を作成し、できるだけ多くの食品を選択します。
  • 重要なコード表示

    • バブルソート
//冒泡排序:筛选贪心位置
double[] proportion = new double[length];
for (int i = 0; i < length; i++) {
    
    
    proportion[i] = lover[i] / prices[i];
}
boolean flag = false;
for (int i = 0; i < length - 1; i++) {
    
    
    for (int j = 0; j < length - 1 - i; j++) {
    
    
        if (proportion[j] > proportion[j + 1]) {
    
    
            flag = true;
            //贪心比
            double temp = proportion[j];
            proportion[j] = proportion[j + 1];
            proportion[j + 1] = temp;
            //食品名
            String name = foodName[j];
            foodName[j] = foodName[j + 1];
            foodName[j + 1] = name;
            //食品价格
            temp = prices[j];
            prices[j] = prices[j + 1];
            prices[j + 1] = temp;
        }
    }
    if (!flag) {
    
    
        break;
    }
    flag = false;
}
  • 貪欲な読み込み
while (sumMoney_4temp > prices[point]) {
    
    
    sumMoney_temp += prices[point];
    sumMoney_4temp -= prices[point];
    foodList_method3.add(foodName[point]);
    point--;
    //对于特别好吃的,最多只能选5种
    if (length - point >= gap) {
    
    
        break;
    }
}
//u:所选产品的倍数,uu:所选产品后,剩余的钱,y:剩余food种类
times = (int) Math.floor(sumMoney / sumMoney_temp);
if (times > 4) {
    
    
    times -= 4;
}
double remain_money = sumMoney - times * sumMoney_temp;
  • 動的プログラミング
//逐层规划,外层循环表示背包重量增加
for (int i = 1; i <= sumMoney; i++) {
    
    
    //内层循环,遍历物品
    for (int j = 1; j <= prices.length; j++) {
    
    

        //如果放入值比背包总重量还大,放弃
        if (prices[j - 1] > i) {
    
    
            bestvalue[i][j] = bestvalue[i][j - 1];
        } else {
    
    
            bestvalue[i][j] =
                    bestvalue[i][j - 1] > bestvalue[(int) Math.floor(i - prices[j - 1])][j - 1] + prices[j - 1] ?
                            bestvalue[i][j - 1] : (int) (bestvalue[(int) Math.floor(i - prices[j - 1])][j - 1] + prices[j - 1]);
        }
    }
}

おすすめ

転載: blog.csdn.net/ljfirst/article/details/107498635