状态压缩dp

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


你可能感兴趣的:(状态压缩dp)