提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
一、题目
题目描述:
小易去附近的商店买苹果,奸诈的商贩使用了捆绑交易,只提供6个每袋和8个每袋的包装(包装不可拆分)。 可是小易现在只想购买恰好n个苹果,小易想购买尽量少的袋数方便携带。如果不能购买恰好n个苹果,小易将不会购买。
输入描述:
输入一个整数n,表示小易想购买n(1 ≤ n ≤ 100)个苹果
输出描述:
输出一个整数表示最少需要购买的袋数,如果不能买恰好n个苹果则输出-1
示例:
输入
20
输出
3
二、题目分析
看到题目的第一个想法是用集合生成,然后打表。想想还要判断所用袋子,好像不怎么靠谱。
然后想到8和6的因子是2和3,3X6=18,2X6=12,超过24的数都可以有8参与。3X8=4X6嘛。
事情就简单了!
三、代码
代码如下:
#include <string>
#include <sstream>
#include <vector>
int solution(int n){
int result=-1;
int bag=0;
while(n>=0){
if(n==0) result = bag;
if(n>=8 && n!=18 && n!=12) n-=8, bag++;
else n-=6, bag++;
}
return result;
}
int main() {
int n;
std::cin>>n;
int result = solution(n);
std::cout<<result<<std::endl;
return 0;
总结
这题找准方向还是很容易的。这种解法肯定不是作者出题的原意,从题目来看:这肯定是为了练习动态规划用的!我这直接上了数学家的方法哈~
那也给个打表的思路,很显然测试数据很小,那么我们可以设立一个一维数组,长度为108好了,然后用一个嵌套循环生成表格:
int vec[108]={0};
for(int i=0; i<108; ++i) vec[i] = -1;
for (int i=0; i<108; i+=8){
for (int j=0; j<108; j+=6){
if(i + j < 108){
vec[i+j] = i/8 + j/6;
}else break;
}
}
这段代码定义了一个大小为108的整数数组,并将其所有元素初始化为0。再将所有元素设置为-1,然后,它使用两个嵌套的for循环来遍历数组中的所有元素。
在第一个for循环中,数组的所有元素都被初始化为-1。在第二个嵌套for循环中,如果一个元素与前一个元素相加后小于108,那么将其添加到数组中。如果一个元素与前一个元素相加后大于等于108,那么跳出内部循环并使用break语句终止循环。如果遍历结束时还有未访问的元素,那么使用else语句跳出内部循环。
这样做可以使代码更加清晰易懂,并且更容易维护。
最后vec[n]就取值就是了。
这里要把6循环放后面,因为放后面的先循环,后面8的循环自然会覆盖同index值的项,显然8的方案比6用的袋少。