hihocoder#1044

 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 }

猜你喜欢

转载自www.cnblogs.com/LeeSongt/p/9332496.html