题意:来自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; }