题意:
有
N
个位置排成一列,对于
第一行为三个正整数n、m和q,意义如前文所述。
第二行为N个整数,分别为 a1 到 an ,代表每一个位置上的数字大小。
分析
状态压缩,设
f[i][j]
为前
i
个数,从
那么对于
可以得到
f[i][j]=Max(f[i−1][j>>1],f[i−1][(j>>1)+(1<<(m−1))])+(j&1)∗w[i]
可以先预处理出
cnt[i]
数组,表示
i
的二进制串中
#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;
}