BZOJ1076

来自蒟蒻XXJ的做题记录

倒着推一遍DP就OK

#include<bits/stdc++.h>
using namespace std;
const int MAXK=128;
const int MAXN=15;
inline int in(){
	int a(0),f(1);char c=getchar();
	while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();}
	while(c>='0'&&c<='9') a=(a<<1)+(a<<3)+c-'0',c=getchar();
	return a*f;
}
int k,n;
int s[MAXN],val[MAXN];
double kkk;
double dp[MAXK][(1<<15)];
void input(){
	k=in();n=in();kkk=n;
	for(int i=1;i<=n;i++){
		val[i]=in();
		int a;
		while(1){
			scanf("%d",&a);
			if(!a) break;
			s[i]|=(1<<(a-1));
		}
	}
}
void xxj(){
	for(int i=k;i;--i)
		for(int j=0;j<(1<<n);j++){
			for(int kk=1;kk<=n;kk++){
				//首先是下一个可以选择的情况
				if((j&s[kk])==s[kk]) dp[i][j]+=max(dp[i+1][j],dp[i+1][j|(1<<(kk-1))]+val[kk]);
				else dp[i][j]+=dp[i+1][j];
			}
			dp[i][j]/=kkk;
		}
}
void output(){
	cout<<fixed<<setprecision(6)<<dp[1][0]<<endl;
}

int main(){
	input();
	xxj();
	output();
	return 0;
}
posted @ 2017-03-31 15:34  Xiaojian_xiang  阅读(313)  评论(1编辑  收藏  举报