Daimayuan Online Judge #665. 数组划分

题目链接

算法分析

线性dp + 贪心 ?

我们若想要每个子数组求和后按与运算的值尽可能的大,按照贪心的思路,我们就从高位上选,若能满足选中这些数位后,还能划分出 k 个字段则说明这个数字可以被选中

那么现在需要解决的问题就是如何判断划分 k 个子段的合法性,假设当前需要验证 x 的合法性

如果一段区间的和 sum[i,j] & x>=x,那么等于就是我们将这个区间加入答案区间中可以贡献出更大的 x ,那么当前的 x 是可以被满足的

那么需要一个 dp 转移一下方案,判断是否可以凑出 >= k 个子段即可

状态表示

dp[i][cnt] 表示前 i 个数中是否可以划分出 cnt 个子段

状态转移

f[0][0] = 1;
    for(int i = 1;i <= n;i ++)//枚举前 n 个数
     for(int j = 0;j < i;j ++)//枚举子区间
      if(((s[i] - s[j]) & x) >= x)//判断是否满足条件
       for(int cnt = 1;cnt <= k;cnt ++)//枚举所有之前可能产生的子段数量
         f[i][cnt] |= f[j][cnt - 1];// 或运算 0 | 1 = 1

[j + 1,i] 这段区间满足条件,那么就可以从前 j 个数划分出 cnt-1 个子段的方案中转移过来

AC Code

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 110;
int a[N],s[N];
int f[N][N];
int n,k;
bool check(int x)
{
    for(int i = 1;i <= n;i ++)
     for(int j = 1;j <= n;j ++)
      f[i][j] = 0;
    
    f[0][0] = 1;
    for(int i = 1;i <= n;i ++)
     for(int j = 0;j < i;j ++)
      if(((s[i] - s[j]) & x) >= x)
       for(int cnt = 1;cnt <= k;cnt ++)
         f[i][cnt] |= f[j][cnt - 1];
         
    return f[n][k];
}

signed main()
{
    
    cin >> n >> k;
    for(int i = 1;i <= n;i ++) scanf("%lld",&a[i]);
    for(int i = 1;i <= n;i ++) s[i] = s[i - 1] + a[i];
    // dp[i][j] 表示前 i 个数中是否可以划分出 j 段子数组 
    
    // 按照高位去贪心 每次 check 这一位是否可以被选择
    // check(int x) check 选取这一位以后的这个数字 是否还能满足 划分出 k 个子段
    int ans = 0;
    for(int i = 52;i >= 0;i --)
    {
        ans = ans | (1ll << i);//验证此时的数是否满足
        if(!check(ans)) ans = ans ^ (1ll << i);//不能满足 就把他消掉 1 ^ 1 = 0
    }
    printf("%lld\n",ans);
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Cold啦啦啦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值