http://hihocoder.com/problemset/problem/1044
可以看出来每一位的选取只与前m位有关,我们把每个位置起始的前m位选取状态看出01序列,就可以作为一个数字来存储,那么将其作为状态,dp[i][j]就是第i个座位前m个座位选取情况为j的最大垃圾处理量。然后取这个序列的后m-1位,和当前位取0/1的情况分别做合法性判断,然后做状态转移即可。
#include <iostream>
using namespace std;
const int N=;
const int inf=;
int dp[N][];
int n,m,q;
int w[N];
int cntb(int num)
{
int c=;
while(num)
c+=num%,num>>=;
return c;
}
int main()
{
cin.sync_with_stdio(false);
while(cin>>n>>m>>q)
{
for(int i=; i<=n; i++)
cin>>w[i];
for(int i=; i<(<<m); i++)
dp[][i]=-inf;
dp[][]=;
int d=<<(m-);
for(int i=; i<=n; i++)
{
for(int j=;j<(<<m);j++)
dp[i][j]=-inf;
for(int j=;j<(<<m);j++)
{
int qc=cntb(j>>);
if(qc>q)continue;
if(qc==q)dp[i][j>>]=max(dp[i][j>>],dp[i-][j]);
else
{
dp[i][d+(j>>)]=max(dp[i][d+(j>>)],dp[i-][j]+w[i]);
dp[i][j>>]=max(dp[i][j>>],dp[i-][j]);
}
}
}
int ans=-inf;
for(int i=;i<(<<m);i++)
ans=max(dp[n][i],ans);
cout<<ans<<endl;
}
return ;
}