1 /* 2 题意:n<=1000, 2<=M<=10,Q<=M,求数组中的最大和,不存在连续的M个中超过Q个被选取 3 思路:状态压缩DP,枚举后面M个数的状态,dp[i][j/2]=max(dp[i-1][j],dp[i-1][j/2+(1<<(m-1))]+a[i])状态转移过程中需满足状态中1个个数小于Q 4 时间:2018.07.18 5 */ 6 #include <bits/stdc++.h> 7 using namespace std; 8 9 typedef long long LL; 10 const int MAXN=100005; 11 const LL MOD7 = 1e9+7; 12 13 int qsize[(1<<10)+5]; 14 int a[1005]; 15 int dp[1005][(1<<10)+5]; 16 int n,m,Q; 17 18 int lowbit(int x) 19 { 20 return x&(-x); 21 } 22 int Count(int x) 23 { 24 int res=0; 25 while (x>0) 26 { 27 ++res; 28 x-=lowbit(x); 29 } 30 return res; 31 } 32 33 void init() 34 { 35 qsize[0]=0; 36 for (int i=1;i<(1<<m);++i) 37 qsize[i]=Count(i); 38 } 39 40 int main() 41 { 42 #ifndef ONLINE_JUDGE 43 freopen("test.txt","r",stdin); 44 #endif // ONLINE_JUDGE 45 scanf("%d%d%d",&n,&m,&Q); 46 for (int i=1;i<=n;++i) scanf("%d",&a[i]); 47 init(); 48 memset(dp,0,sizeof(dp)); 49 int st = 1<<(m-1); 50 for (int i=1;i<=n;++i) 51 { 52 for (int j=0;j<(1<<m);++j) 53 { 54 if (qsize[j]<=Q) dp[i][j/2] = max(dp[i][j/2],dp[i-1][j]); 55 if (qsize[j]<=Q && qsize[j/2+st]<=Q) dp[i][j/2+st]=max(dp[i][j/2+st],dp[i-1][j]+a[i]); 56 } 57 } 58 // for (int i=1;i<=n;++i) 59 // { 60 // for (int j=0;j<(1<<m);++j) 61 // printf("dp[%d][%d]=%d\n",i,j,dp[i][j]); 62 // } 63 int ans=0; 64 for (int j=0;j<(1<<m);++j) 65 if (qsize[j]<=Q) ans = max(ans, dp[n][j]); 66 printf("%d\n",ans); 67 return 0; 68 }