可乐

题目描述

猪年快乐!在这个快乐的日子里我们当然要去超市买可乐喝啦! 
现在超市有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(V$_{buy}$) + min(V$_{left}$),我们有两种选择,第一是再买一瓶单位价值最便宜的可乐;第二就是在剩下的可乐品类中选择,求min(V$_{left}$)(其实就是解法相同的子问题)。我们在这两种选择中寻找最小值即可。

#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;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值