今天小伙伴在群里给出了一道题
【分享一道题,有兴趣的可以做做哈。假设《冰与火之歌》有五卷,每一卷单独买是20块。两卷连买减5%,三卷连买减10%,四卷连买减20%,五卷连买减25%,买相同的卷不打折。比如买两本卷一,一本卷二,总价格是58元。现买了一批书N,计算出它的最低价格。】
一看到这道题,瞬间就觉得这么简单有什么值得做的,于是三下五除二写了这么一个算法:
double money(int* A){
double result = 0;
if(A==null)
return -1;
for(int i=0; i<5; i++){
result += (A[i]/5)*20*0.75 + (A[i]%5/4)*20*0.80 + (A[i]%5%4/3)*20*0.90 + (A[i]%5%4%3/2)*20*0.95 + (A[i]%5%4%3%2)*20
}
return result;
}
简单粗鲁的贪心算法。于是遭到了小伙伴的反击,说我把问题想简单了。
例如:8本书,买两个四本比一个五本一个三本更便宜。
我的算法不仅不美,甚至不是最优解。
然后瞬间我又把问题做复杂了,买五种书,一毛钱都不便宜的情况一定是最后需要考虑的,那么我们只需要考虑买书的先后顺序就可以了,做一个A(4,4) 的全排列。然后再根据实际的优惠情况对A(4,4)种排列里,明显不是最优解的给剔除进行优化。
一个很复杂,宏观的想法,可行性有,但是太复杂。
然后看了编程之美给的解法,题目中给的数据,4+4的组合比5+3的组合更优,而且有且仅有这一个特例,所以根据这种情况,对代码进行优化
double money(int* A){
double result = 0;
if(A==null)
return -1;
for(int i=0; i<5; i++){
result += (A[i]/8)*40*0.80 + (A[i]%8/5)*20*0.75 + (A[i]%8%5/4)*20*0.80 + (A[i]%8%5%4/3)*20*0.90 + (A[i]%8%5%4%3/2)*20*0.95 + (A[i]%8%5%4%3%2)*20
}
return result;
}
把 A[i]/8 特殊组合揪出去单独处理一下。
其实这个题难点是数据统计,对特殊数据的敏感度,要把(4+4)这个特殊情况给分解出来