【JZOJ6350】考试(test)

description


analysis

  • 对于(n=0)的点,直接模拟就好了

  • 状压(DP),设(f[i][j][S])表示到第(i)题、连续(GG)(j)题、喝的饮料集合为(S)的最大答案

  • 由于一题可以喝多瓶饮料所以转移需要枚举(S)的子集(SS)来转移

  • 然后转移比较显然但是细节恶心

  • 我不会告诉你我一共打了三个DP然后调出来其中一个才切的


code

#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include<stdio.h>
#include<string.h>
#include<iostream>
#define MAXN 105
#define MAX 500005
#define ha 19260817
#define db double
#define ll long long
#define reg register ll
#define fo(i,a,b) for (reg i=a;i<=b;++i)
#define fd(i,a,b) for (reg i=a;i>=b;--i)

using namespace std;

db f[MAXN][MAXN][3000],val[3000][3000];
ll x[MAX],yy[MAX],y[MAX],down[MAX],a[MAX],dif[MAX];
ll n,m,k,last;
db ans;

inline ll read()
{
	ll x=0,f=1;char ch=getchar();
	while (ch<'0' || '9'<ch){if (ch=='-')f=-1;ch=getchar();}
	while ('0'<=ch && ch<='9')x=x*10+ch-'0',ch=getchar();
	return x*f;
}
inline db sqr(db x){return x*x;}
inline db max(db x,db y){return x>y?x:y;}
inline db min(db x,db y){return x<y?x:y;}
int main()
{
	freopen("T1.in","r",stdin);
	//freopen("test.in","r",stdin);
	//freopen("test.out","w",stdout);
	n=read(),m=read(),k=read();
	fo(i,1,n)x[i]=read();fo(i,1,m)yy[i]=read();fo(i,1,k-1)down[i]=read();
	fo(i,1,k)a[i]=read(),y[i]=yy[read()],dif[i]=read();
	if (n==0)
	{
		db anss=0;
		fo(i,1,k)
		{
			db prob=a[i]*(1-sqr(max(0,1-1.0*y[i]*(last?(1.0-down[i-last]/100.0):1)/dif[i])));
			if (prob<0.64*a[i])last=i;anss+=prob;
		}
		printf("%.2lf
",anss);
		return 0;
	}
	fo(i,0,k)fo(j,0,k)fo(l,0,(1<<n)-1)f[i][j][l]=-ha;
	f[0][0][(1<<n)-1]=0;
	
	fo(S,0,(1<<n)-1)
	{
		for (reg SS=S;SS>=0;SS=(SS-1)&S)
		{
			val[S][SS]=1.0;
			fo(i,1,n)if ((S&(1<<(i-1))) && (!(SS&(1<<(i-1)))))val[S][SS]*=1+x[i]/100.0;
			if (!SS)break;
		}
	}

	fo(i,1,k)
	{
		fo(j,0,i)
		{
			fo(S,0,(1<<n)-1)if (f[i-1][j][S]>=0)
			{
				for (reg SS=S;SS>=0;SS=(SS-1)&S)
				{
					db pro=val[S][SS];
					if (j)
					{
						db tmp=a[i]*(1-sqr(max(0,1-1.0*(y[i]*pro*(1-down[j]/100.0))/dif[i])));
						if (tmp>=0.64*a[i])f[i][j+1][SS]=max(f[i][j+1][SS],f[i-1][j][S]+tmp);
						else f[i][1][SS]=max(f[i][1][SS],f[i-1][j][S]+tmp);
					}
					else
					{
						db tmp=a[i]*(1-sqr(max(0,1-1.0*(y[i]*pro)/dif[i])));
						if (tmp>=0.64*a[i])f[i][0][SS]=max(f[i][0][SS],f[i-1][0][S]+tmp);
						else f[i][1][SS]=max(f[i][1][SS],f[i-1][0][S]+tmp);
					}
					if (!SS)break;
				}
			}
		}
	}
	fo(i,0,k)fo(j,0,(1<<n)-1)ans=max(ans,f[k][i][j]);
	printf("%.2lf
",ans);
	return 0;
}
原文地址:https://www.cnblogs.com/horizonwd/p/11535777.html