取数字

题意:

N 个位置排成一列,对于ai位置上有一个值为 wi 的数字,现要求在任意的 m 个连续的位置中取出不超过q个位置的数,求能取出的数的最大值

第一行为三个正整数n、m和q,意义如前文所述。

第二行为N个整数,分别为 a1 an ,代表每一个位置上的数字大小。

分析

状态压缩,设 f[i][j] 为前 i 个数,从i im+1 的取出数字的情况用 j 的二进制串表示

那么对于f[i][j]有两种决策,对于 im+1 有取或不取两种分案

可以得到
f[i][j]=Max(f[i1][j>>1],f[i1][(j>>1)+(1<<(m1))])+(j&1)w[i]

可以先预处理出 cnt[i] 数组,表示 i 的二进制串中1的个数

#include <cstdio>
#include <algorithm>

using namespace std;

template <class T>T Max(const T &a, const T &b) {return a > b ? a : b;}

const int SN =1000 + 10;

int f[SN][1<<11], n, m, q, w[SN];
int cnt[1<<11];

void Read(int &x) {
    int in = 0,f = 1; char ch = getchar();
    while(ch<'0' || ch>'9') {if(ch=='-') f = -1;ch = getchar();}
    while(ch>='0' && ch<='9') {in = in*10+ch-'0';ch = getchar();}
    x = in*f;
}

void pre() {
    cnt[1] = 1;
    for(int i = 2; i < (1<<11); i++) //这里参数弄错,WA了几发
        cnt[i] = cnt[i>>1] + (i&1);
}

int main() {

    Read(n),Read(m),Read(q);

    for(int i = 1; i <= n; i++) Read(w[i]);

    pre();

    int maxn = 1<<m;
    int std1 = 1 << (m-1);

    for(int i = 1; i <= n; i++)
        for(int j = 0; j < maxn; j++) {
            if(cnt[j] <= q) 
                f[i][j] = Max(f[i-1][j>>1], f[i-1][(j>>1)+std1]) + (j&1)*w[i];
        }

    printf("%d\n",*max_element(f[n],f[n]+maxn));

    return 0;

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值