题意:来自hihoCoder(第八周)。小Hi和小Ho所处的车厢可以被抽象成连成一列的N个位置,按顺序分别编号为1..N,每个位置上都有且仅有一名乘客在休息。同时每个位置上都有一些垃圾需要被清理,其中第i个位置的垃圾数量为Wi。乘务员可以选择其中一些位置进行清理,但是值得注意的是,一旦有编号连续的M个位置中有超过Q个的位置都在这一次清理中被选中的话(即这M个位置上的乘客有至少Q+1个被惊醒了),就会发生令人不愉快的口角。而小Hi和小Ho的任务是,计算选择哪些位置进行清理,在不发生口角的情况下,清扫尽可能多的垃圾。
输入:每个测试点(输入文件)有且仅有一组测试数据。每组测试数据的第一行为三个正整数N、M和Q,意义如前文所述。每组测试数据的第二行为N个整数,分别为W1到WN,代表每一个位置上的垃圾数目。对于100%的数据,满足N<=1000, 2<=M<=10,1<=Q<=M, Wi<=100
输出:对于每组测试数据,输出一个整数Ans,表示在不发生口角的情况下,乘务员最多可以清扫的垃圾数目。样例输入:
5 2 1
36 9 80 69 85样例输出:
201
#include <stdio.h>
#include <string.h>
#define max(a,b) ((a)>(b)?(a):(b))
#define N 1005
int s[N],dp[2][1<<10];
int n,m,M,k;
int digit(x){
int res=0;
while(x){
res += x&1;
x >>= 1;
}
return res;
}
int testfirstline(int x){
int i,res=0,temp;
if(digit(x)>k)
return 0;
temp = 1<<(M-1);
for(i = 0;i<M;i++){
if(temp & x)
res += s[i];
temp >>= 1;
}
return res;
}
int test(int now,int x){
int res=0,temp=1<<(M-1);
if(digit(x)>k)
return 0;
if(x&1)
res += s[now];
x >>= 1;
return res+max(dp[0][x],dp[0][x|temp]);
}
int main(){
freopen("a.txt","r",stdin);
while(scanf("%d %d %d",&n,&M,&k)!=EOF){
int i,j,ans=0;
for(i = 0;i<n;i++)
scanf("%d",&s[i]);
m = 1<<M;
for(i = 0;i<m;i++)
dp[0][i] = testfirstline(i);
for(i = M;i<n;i++){
for(j = 0;j<m;j++)
dp[1][j] = test(i,j);
for(j = 0;j<m;j++)
dp[0][j] = dp[1][j];
}
for(i = 0;i<m;i++)
ans = max(ans,dp[0][i]);//dp[0][i]而不是dp[1][i],考虑M==n的时候
printf("%d\n",ans);
}
return 0;
}