[SCOI2008]奖励关

题目

思路

显然状态压缩DP,先设(f_{i,S})表示到了第(i)轮,状态为(S)时的最大价值,用刷表法正推求解;

然后就发现有些问题,因为就连题目都举了个栗子说明你当前的决策需要考虑未来的情况,这样会有后效性

所以需要逆推求解,设(f_{i,S})表示还剩(i)论,状态为(S)时的最大价值,每次决策选或者不选,用刷表法逆推求解

Code

#include<bits/stdc++.h>
#define N 105
#define M 16 
using namespace std;
int k,n,rf[M],p[M];
double f[N][1<<M];//当前还有i次机会,当前状态为j的未来期望价值 

template <class T>
void read(T &x)
{
	char c;int sign=1;
	while((c=getchar())>'9'||c<'0') if(c=='-') sign=-1; x=c-48;
	while((c=getchar())>='0'&&c<='9') x=x*10+c-48; x*=sign;
}

int main()
{
	read(k);read(n);
	for(int i=1;i<=n;++i)
	{
		read(p[i]);
		while(1)
		{
			int x; read(x); 
			if(!x) break;
			rf[i]|=(1<<(x-1));
		}
	}
	for(int i=0;i<k;++i)
	  for(int j=0,t=(1<<n);j<t;++j)//i+1层为j状态 
		for(int q=1;q<=n;++q)//选q 
		{
			if((rf[q]&j)!=rf[q]) f[i+1][j]+=f[i][j]/n;
			else f[i+1][j] += max( (p[q] + f[i][j|(1<<(q-1))]) /n , f[i][j] /n );
		}
	printf("%.6lf
",f[k][0]);
	return 0;
}
原文地址:https://www.cnblogs.com/Chtholly/p/11691740.html