前言
遇到这题好几回了!可我一直没能通过…
一直以为是水平问题,害我严重怀疑小学数学没过关。今天又遇到了它,我又是各种折腾啊~ 没办法的时候我都去偷师了,CSDN网上有二篇写这题的!不过也没比我的小学数学好到哪去,也不知能不能过了100%,反正我怎么改都是90%,我看着思路都差不多,没图没证据!
然后我又去找GPT请教,都请教到不理我了!回答问题次数到了,也没问出个所以然,GPT在这题上幼儿园都没毕业!
想到我还有文心一言!我找小文去问问!
小文给了我如下代码:
cpp
复制代码
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <algorithm>
using namespace std;
int find_if(int n, std::vector<int> &vec){
int result=0;
// TODO:
sort(vec.begin(),vec.end());
int sum = 0, i = 0;
while(sum < m){
sum += (i < vec.size() ? vec[i] : vec[i-1]);
i++;
}
return result;
}
int solution(int n, int m, std::vector<int>& vec){
int result=0;
// TODO:
sort(vec.begin(),vec.end());
int sum = 0, i = 0;
while(sum < m){
sum += find_if(sum+1, vec);
cout << "now sum = " << sum << endl;
result++, i++;
}
return result;
}
这个才让人无语…我就问小文:
然后它就成复读机了…
复读了两回后,我忍不住了!bty:GPT也被问复读了,别因此段对话以为GPT比小文好,至少在这个问题上都一样!
最后下定决心复习小学数学~ 请教了隔壁家8岁小孩,终于搞定了!
有图为证:
1. 题目
题目描述:
小A有n枚硬币,现在要买一样不超过m元的商品,他不想被找零,同时又不想带太多的硬币,且硬币可以重复,现在已知这n枚硬币的价值,请问最少需要多少硬币就能组合成所有可能的价格?
输入描述:
第一行两个数:n、m。 下一行,共n个数字,表示硬币的面值。
输出描述:
一行一个数,表示最少需要多少硬币。如果无解请输出“No answer!!!”
示例:
输入
5 31
1 2 8 4 16
输出
5
2. 分析
首先,这题要仔细读题,最先我就踩了没仔细读题的坑,我给看成要用n个硬币凑出m的值,最无语的是样例也这么误导人。多次0%再重读题后搞明白了是要求,用n个面值的无限数量的硬币,凑出m及以下的任意值!因为预估的是最高值为m,很可能价格要低,又不要找零(虽然他自己带一堆零钱),但他就这么任性!这样我们就可以分析出(以示例来看):
首先要取的是1面值的一个,因为货物价格可能是1至m!
然后取2面值一个,这样可以组合出1,2,3。 以此类推。
那假设没有4面值怎么办?很显然就再取一个2,这样能组合出1,2,3,4,5。一个还不够!再来一个2面值,就有1到7,然后再取8面值一个。
以此推导…这有了主要思路,就可以写代码了,写完再改嘛~
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <algorithm>
using namespace std;
int solution(int n, int m, std::vector<int>& vec){
int result=0;
// TODO:
sort(vec.begin(), vec.end());
int sum = 0, i = 0, L = vec.size(), tmp;
if (*max_element(vec.begin(),vec.end())==1) sum = m, result = m; //注1
while(sum<m && L>1){
if (find(vec.begin(), vec.end(), 1) == vec.end()) { //注2
//cout << "No answer!!!";
result = 0;
break;
}
if(sum+1 < vec[i+1]){
tmp = vec[i];
sum += tmp;
result++;
}else if(sum+1 == vec[i+1]){
tmp = vec[i+1];
sum += tmp;
result++;
i++;
}else{
i++;
}
if (i == L-1){ //注3
int sum_sub = (m-sum);
result += (sum_sub/vec[L-1]) + (bool(sum_sub%vec[L-1]));
break;
}
}
return result;
}
注1:此处原没写得这么复杂,原是写在循环内的判断,如果vec[0]不为1,就输出No answer!!!,后来因为老过不了,就给改成这样了,这句是为了防止1 0 0 0 1这样的输入面值,因为排序后,0在最前面,就可能得不到正确结果,实际多次测试来看,没有这样的测试数据,所以这句可以没有。
注2:此处同上原因改的,注1 是防止只有1的情况,这是防止排序后0在最前的问题。
注3:这里其实不要也能得出正确结果,但是会超时,这样写是在当取到最大面值后,没必要再一个个去取了,直接取最大的,用的除法一次算出。
其实估计很多人都做出类似的答案了,但就算这样也只能过90%!
这就对了,真的!剩下的是题目的坑,去看main函数吧~
总结
最后隔壁小孩告诉我:抄答案是不对的!所以我就把答案写出来了~
把main的输出std::cout改一改就好了!