分析:状态压缩DP。
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; int w[2000],dp[1001][1<<11]; /*int sum(int x) { int ans=0; while(x) { ans+=x%2;x/=2; } return ans; }*/ int sum(int x) { int ans=0; while(x>0) { ans+=(x&1); x>>=1; } return ans; } int main() { int N,M,Q; scanf("%d%d%d",&N,&M,&Q); for(int i=1;i<=N;i++) scanf("%d",&w[i]); /*dp[i][S]表示位置i到i-m+1这m个位置状态为S时的最大清扫数量 当S中的1等于Q时,第i个位置就不能选取,dp[i][S]=max(dp[i-1][S>>1],dp[i-1][S>>1+(1<<m-1)]) S第0位即表示i是否选取 */ for(int i=1;i<=N;i++) { for(int S=0;S<(1<<min(i,M));S++) if(sum(S)<=Q) { if(S&1)//第i位被选中 dp[i][S]=max(dp[i-1][S>>1],dp[i-1][(S>>1)+(1<<M-1)])+w[i]; else //第i位不被选中 dp[i][S]=max(dp[i-1][S>>1],dp[i-1][(S>>1)+(1<<M-1)]); } } int ans=dp[N][0]; for(int i=1;i<(1<<min(N,M));i++) ans=max(ans,dp[N][i]); printf("%d\n",ans); return 0; }