题目描述
猪年快乐!在这个快乐的日子里我们当然要去超市买可乐喝啦!
现在超市有n种可乐,第 i 种可乐的价格为C[i] ,体积为 2i-1 毫升,每种可乐都是无限供应的 ,现在你想买至少 L毫升的可乐 ,作为一个省钱小能手,聪明的你能够想到最少要花多少钱吗?
输入
输入包含多组测试用例。
每组测试用例第一行包含两个数字 n 和 L (1 ≤ n ≤ 30; 1 ≤ L ≤ 109) , n是可乐的种类数, L是我们最终要买的可乐体积。
第二行包含 n 个数字 C1,C2,...Cn n (1 ≤ ci ≤ 109) ,代表每一种可乐的价格。
输出
输出一个数字 , 购买至少L毫升的可乐需要的最少花费。
样例输入
4 12
20 30 70 90
4 3
10000 1000 100 10
4 3
10 100 1000 10000
样例输出
150
10
30
分析:
本题使用贪心算法,贪心策略是选择单位价值最低的可乐,两个重要的问题就是贪心选择性和最优子结构。
最优子结构:设min(L)是购买大于等于L毫升可乐所需要的最小花费,那么买第一毫升可乐时有:min(L) = unit_v + min(L - 1),原问题的最优解中含有子问题的最优解,这就是该问题的最优子结构。
贪心选择性:我们假设花费最少的情况下,买的可乐每毫升的价值分别为{v1, v2, v3, ... vi},如果v1不是最低的单位价值,我们将其替换成最低的单位价值min_unit_v1,则{min_unit_v1, v2, v3, ... vi}是最优解。同理我们通过贪心策略,将其替换为{min_unit_v1, min_unit_2, ..., min_unit_vi}是最优解。即局部最优可以获得全局最优。
这里遇到一个问题就是,可乐并不是一毫升一毫升卖的,而是一瓶一瓶卖的。如果L恰好被单位价值最便宜的可乐买完,那么每一毫升都是以最低价格买的,显然这就是答案。如果还有剩余呢?就是说当前选择的可乐容量大于我们需要的毫升数,问题转化为min(L) = min() + min(
),我们有两种选择,第一是再买一瓶单位价值最便宜的可乐;第二就是在剩下的可乐品类中选择,求min(
)(其实就是解法相同的子问题)。我们在这两种选择中寻找最小值即可。
#include<bits/stdc++.h>
using namespace std;
struct Cola{
int price;
long long volume;
double unit_p;
};
bool cmp(Cola a, Cola b){
return a.unit_p <= b.unit_p;
}
int main(){
ios::sync_with_stdio(false); cin.tie(0);
int n, L;
while(cin >> n >> L){
long long cost = 0, ans = LLONG_MAX, temp = 0;
int left = 0;
Cola cola[30];
for(int i = 0; i < n; i++){
cin >> cola[i].price;
cola[i].volume = 1 << i;
cola[i].unit_p = cola[i].price * 1.0 / cola[i].volume;
}
sort(cola, cola + n, cmp);
left = L;
for(int i = 0; i < n; i++){
cost += left / cola[i].volume * cola[i].price;
left = left % cola[i].volume;
if(left == 0){
ans = min(cost, ans);
break;
}else{
temp = cost + cola[i].price;
ans = min(ans, temp);
}
}
cout << ans << endl;
}
return 0;
}