点完菜,他们发现好像觉得少了点什么?
想想马上就要回老家了某不愿透露姓名的林姓学长再次却陷入了沉思。。。。。。。。。
他默默的去前台打算点几瓶二锅头。
他发现菜单上有n 种不同毫升的酒. 第 i 种有2i - 1 毫升价格为ci 元.商店中每种类型的酒的数量可以被认为是无限的。.
他对于自己能喝多少还是有点B-Tree的,但是他认为喝酒一定要喝的尽兴,于是他打算买至少L 毫升,但是又要花最少的钱,现在他想知道他最少需要花多少钱
Input
第一行输入两个整数 n and L (1 ≤ n ≤ 30; 1 ≤ L ≤ 109) — 代表有n总酒和需要买的数量
第二行输入 n个整数s c1, c2, ..., cn (1 ≤ ci ≤ 109) —代表第i种酒需要的钱数
Output
输出一个整数,他买至少L 了毫升,所花的最少钱数
Example
Input
4 12
20 30 70 90
Output
150
Input
4 3
10000 1000 100 10
Output
10
Input
4 3
10 100 1000 10000
Output
30
Input
5 787787787
123456789 234567890 345678901 456789012 987654321
Output
44981600785557577
Note
在第一个例子中,你应该花90元购买一个8毫升的,花60元的购买两个2毫升的。总共你会得到12毫升只要150元。
在第二个例子中,即使你只需要3毫升,但是购买一个10元8毫升的便宜一些。
在第三个例子中,最好10元购买三个1毫升的。
题解: 1 先按照性价比排序,优先购买性价比最高的物品,买到最大限度。
2 用sum记录当前所花的钱,用ans记录档购买大于等于L升时所花费的最小值。
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; typedef long long ll; const ll INF=9223372036854775807-1; //9223372036854775807 longlong的最大值 const int N=40; struct stu{ ll price; ll v; bool friend operator < (const stu &x,const stu &y){ return x.price * y.v < y.price *x.v; } }arr[N]; int main(){ int n,need; cin>>n>>need; for(int i=1;i<=n;i++){ scanf("%d",&arr[i].price); arr[i].v=1<<(i-1); } sort(arr+1,arr+1+n); ll res=need; ll l=1; ll sum=0; ll ans=INF; while(res>0&&l<=n){ sum+=res/arr[l].v*arr[l].price;//购买的最大限度时res/arr[l].v res=res%arr[l].v;//res是购买完l号饮料,距离need还差多少. if(res==0) ans=min(ans,sum);//恰好购买完的话,保留一下当前状态 else ans=min(ans,sum+arr[l].price);//如果res!=0的话,那就再多买一个价格就是sum+arr[l].price; l++; } printf("%lld\n",ans); return 0; }