此为笔试题一
一、某蛋糕店推出一种礼品卡,使用该卡可以用于购买店内的蛋糕,每种蛋糕限购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 }