线性规划算法实现一需求回溯打表

此为笔试题一

一、某蛋糕店推出一种礼品卡,使用该卡可以用于购买店内的蛋糕,每种蛋糕限购1个。该卡片面值为R元,仅可以使用1次,结账后卡内剩下的余额作废。已知店内的全部种类的蛋糕价格都为整数,求出怎么购买,可使结账后卡内剩下的余额最少。

题目求的是怎样购买,而不仅仅是0-1背包问题,那么,就应该保留各个决策状态等待回溯(可能有多个结果,故不能保留最后的状态)

回朔时应该注意避免无效输出

  1 #include "pch.h"
  2 #include <iostream>
  3 #include<string>
  4 using namespace std;
  5 static const int M = 20;
  6 static const int array_[] = { 1,2,5,9,10,11,8,3,20,80 };
  7 
  8 int** test(int &n)
  9 {
 10     //M为购物卡的数值,array_为蛋糕初始值
 11 
 12     n = sizeof(array_) / sizeof(int);
 13     int **p = new int*[n];
 14     for (int i = 0; i < n; i++)
 15     {
 16         p[i] = new int[M + 1];
 17     }
 18     for (int i = 0; i < n; i++)
 19         for (int j = 0; j <= M; j++)
 20             p[i][j] = 0;
 21 
 22     //线形规划
 23     //将p[0]赋值
 24     if (array_[0] <= M)p[0][array_[0]] = array_[0];
 25     for (int i = 1; i < n; i++)
 26     {
 27         //前面都不买,从这个开始买
 28         if (array_[i] <= M)
 29         {
 30             p[i][array_[i]] = array_[i];
 31         }
 32         //累计情况,从上一次情况进行判定,这是买
 33         for (int j = 1; j <= M; j++)
 34         {
 35             if (p[i - 1][j] != 0)
 36             {
 37                 int value = p[i - 1][j] + array_[i];
 38                 //如果购买该层商品
 39                 if (value <= M)
 40                 {
 41                     p[i][value] = value;
 42 
 43                 }
 44                 //如果不买该层商品
 45                 //这个用于打表递归回溯所有方法,如果仅打出一种方法的话去掉这条即可
 46 
 47                 p[i][j] = p[i - 1][j];
 48 
 49 
 50             }
 51         }
 52 
 53     }
 54 
 55     for (int i = 0; i < n; i++)
 56     {
 57         for (int j = 1; j <= M; j++)
 58         {
 59             cout << p[i][j] << " ";
 60         }
 61         cout << endl;
 62     }
 63     return p;
 64 }
 65 
 66 
 67 //检索当前为第n层,剩余金额为value
 68 int doprint(int **p, int n, int value)
 69 {
 70     int sum = 0;
 71     //如果能买完,直接终止
 72     if (value - array_[n] == 0)
 73     {
 74         cout << array_[n] << endl;
 75         return 1;
 76     }
 77     int left = value - array_[n];
 78     if (left > 0)
 79     {
 80 
 81         for (int i = n - 1; i >= 0; i--)
 82         {
 83             //由于数据是继承的,每层状态的打表代表没一层状态可能出现的余额,但是,这并不是每层非0的值都有意义
 84             //当且仅当其余额足够购买才能进行打表递归(即  left-array_[i]>=0),不满足该条件则为无效递归
 85             //即实际上出现该层的状态是继承的,而不是购买后得来的
 86             if (p[i][left] != 0 && left - array_[i] >= 0)
 87             {
 88                 cout << array_[n] << " ";
 89                 sum += doprint(p, i, left);
 90             }
 91         }
 92     }
 93     return sum;
 94 
 95 }
 96 
 97 int main()
 98 {
 99     //线形规划,并输出规划后各阶段购买情况
100     //M为购物卡的数值,array_为蛋糕初始值
101     int n = 0;
102     int **p = test(n);
103     int max = 0;
104     //检索最大值
105     for (int i = n - 1; i >= 0; i--)
106     {
107         for (int j = M; j >= 1; j--)
108         {
109             if (p[i][j])
110             {
111                 max = p[i][j];
112                 break;
113             }
114         }
115         if (max)break;
116     }
117     cout << "-----------------------------" << endl;
118     int sum = 0;
119     for (int i = n - 1; i >= 0; i--)
120     {
121         sum += doprint(p, i, max);
122     }
123     cout << "一共有  " << sum << "种买法" << endl;
124     cout << "可综合使用最大面值为 " << max << endl;
125 
126 }

猜你喜欢

转载自www.cnblogs.com/jing19960917/p/11411513.html
今日推荐