描述 | |
计算概论期终考试结束后,同学B感觉自己得到了解脱。回想起复习期间的艰苦岁月,B决定去某新开的食堂大吃一顿。 B同学希望今天把饭卡的钱全部花完,以抚慰自己受伤的心灵。 已知B的饭卡里有钱p元,给定食堂物品的价格列表(价格不重复),请你给出所有可能的恰好把p元花掉的购买选择。 如:p=7, 食堂现有价格为 [3,2,6,7] 的物品,则可能的购买选择有: [3, 2, 2] [7] 每种价格的物品可以多次选购。 | |
关于输入 | |
n+1行 第1行有两个整数,分别为物品种类n, 以及B卡里多少钱p。 接下来有n行,每行一个数,为每种物品的价格xi。 满足:3<= n <= 10;2<= p <= 200;2<= xi <=100。 | |
关于输出 | |
所有可能的购买选择,每种选择一行,要求不重复。 对于每一种选择,价格的顺序要求按照输入顺序。 每种物品可以多次选购无限制。 如果没有恰好花掉的选择,则输出"NO"。 | |
例子输入 | |
4 7 3 2 6 7 | |
例子输出 | |
3 2 2 7 |
思路:
本题递归时有两种情况:
①选择第k件物品,下次仍从第k件物品开始(因为物品可重复)
②不选择第k件物品,下次从第k+1件物品开始
#include<iostream>
using namespace std;
int n;
int p;
int cost[11] = {};
int num = 0;
int choose[30] = {};
int x = 0;
void f(int k, int y)//第k个物品,目前的消费y元
{
if (y == p) {//如果恰好花完p元
++num;
for (int i = 0; i < x; ++i) {//输出所储存的方案
cout << choose[i];
if (i < x - 1) {
cout << " ";
}
}
cout << endl;
return;
}
if (k == n || y > p) {//如果没有恰好花完p元,返回
return;
}
choose[x++] = cost[k];//如果选择了第k件物品
f(k, y + cost[k]);//继续消费
x--;//回溯
choose[x] = 0;//回溯
f(k + 1, y);//如果不选择第k件物品
}
int main()
{
cin >> n >> p;
for (int i = 0; i < n; ++i) {
cin >> cost[i];
}
f(0, 0);
if (!num) {
cout << "NO";
}
return 0;
}