020 Bookshelves (CF981D)

本文解析了CF981D题目,介绍了如何通过贪心算法与动态规划结合的方法来解决书架摆放问题,以求得最大的美观程度。文章详细解释了按位与运算,并给出了解决方案的具体实现。

题目链接:CF981D

  • 标签:按位、贪心、DP

  • 大意:有n本书,每本书都有一个价值a。将这n本书按照顺序连续地放在书架上(读题的时候忽略了“连续的”这个重要讯息,导致很长时间都没有思路),定义一个书架的美观程度为这个书架上所有书价值的总和,k个书架的美观程度为每个书架的按位与和,求这k个书架的最大美观程度。

  • 思路:先简单介绍一下按位与运算(自己对位运算不太熟悉老是碰壁)

    • 按位与(&):运算规则:只有两个数的二进制同时为1,结果才为1,否则为0。(负数按补码形式参加按位与运算)

      0 & 0= 0 ,0 & 1= 0,1 & 0= 0, 1 & 1= 1。

    • 借机补充一个常用的运算:移位运算:(<</>>)效果很简单,就是数向左/右移一位,左移时在最右端补0,右移时在最左端补1,由二进制的性质可知:
      n * 2 == (n << 1)
      n / 2 ==(n >> 1)
      1 << n == pow (2 , n)

    • 了解了按位与运算的特性后,我们不难由高位至低位进行贪心选择:如果最大位为1肯定要优于此位为0,而将多少个书放在一起,可以利用区间dp

    • dp[i][j]表示前i个书架放了j本书

  • 代码:

#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int maxn=60;

LL dp[maxn][maxn],a[maxn];
LL sum[maxn],n,k;

int main() {
    cin>>n>>k;
    for(int i=1;i<=n;i++) {
        cin>>a[i];
        sum[i]=sum[i-1]+a[i];//计算前i项和 
    }
    LL ans=0;
    for(int bit=55;bit>=0;bit--) {//从最高位开始判断可否为1 
        LL num=(LL)1<<bit;//2的bit次方 (10000…0000) 
        memset(dp,0,sizeof(dp));
        dp[0][0] = 1;
         for(int l=1;l<=k;l++) {//放进k个书架里 
            for(int i=1;i<=n;i++) {//总共n本书 
                for(int j=0;j<i;j++) {//前一个书架放j本书 
                    if(dp[l-1][j]&&((sum[i]-sum[j])&num)&&(((sum[i]-sum[j])&ans)==ans))
					//如果前一个书架放j本书可行,且j+1~i号书之和(当前书架的和)的bit位是1,且不会令前置位丢1  
                        dp[l][i] = 1;//该位置可行 
                }
            }
        }
        if(dp[k][n]) ans+=num; 
    }
    cout<<ans;
}

(第一次发现原来插入代码块的时候是可以选择语言的,难怪我之前的代码不亮了)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值