CF913C dp+贪心+数位

1 篇文章 0 订阅

题目链接:

点这里

题目大意:

给定n和L,接下来n个数,第i个数 ai (0<=i<=n-1)代表购买 2i1 个物品的花费,要求购买不少于L个的最小花费是多少

思路:

n,L的数值都比较大,使用多重背包不可行,观察题目可以发现,答案很可能与二进制位有关。可以想到, ai ai+1 之间有三种关系
①2* ai = ai+1
②2* ai < ai+1
③2* ai > ai+1
在第一种关系下,无论是选择 ai 还是 ai+1 对答案没有影响
在第二种关系下,则应购买两个 ai 而不是一个 ai+1
在第三种关系下,应该选用 ai+1 而不是两个 ai
因此,我们可以得出购买 2k 件商品的最优解

思考一个问题:假设恰好需要购买L件,而不是大于等于L件,这个时候,只要在以上的基础,把L对应二进制位上的 ai 全部加起来就是最优解。

当可以购买大于等于L件商品的时候的最优解:假设购买了M件商品为最优解,M>=L。此时从高位到低位,M与L的二进制第一次出现不同的位置i所对应的 ai 小于L比i小的所有位 ai 的和。从这个角度出发可得最优解。

代码:

#include <iostream>
#include <bits/stdc++.h>

using namespace std;
long long INF=9223372036854775807;
long long s[31];
long long dp[31];
long long a[31];
int main()
{
    int n,L;
    memset(a,0,sizeof a);
    scanf("%d%d",&n,&L);
    for(int i=0;i<n;i++)
    {
        scanf("%I64d",&dp[i]);
    }
    for(int i=0;i<n-1;i++)
    {
        dp[i+1]=min(dp[i+1],2*dp[i]);
    }
    long long ans=INF;
    long long sum=0;
    for(int i=n-1;i>=0;i--)
    {
        long long need=L/(1<<i);
        sum+=need*dp[i];
        L-= need<<i;
        ans=min(ans,sum+(L>0)*dp[i]);/**(L>0)代表有余数,当前位的低位还有1**/
    }
    printf("%I64d\n",ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值