BZOJ 1076 [SCOI2008]奖励关

来源:互联网 发布:sql unique用法 编辑:程序博客网 时间:2024/05/29 09:13

看了数据范围一目了然是状态压缩,然而对于每种情况有选和不选两种情况,记录已选的状态,每次枚举关卡时判断是否已选。

注意这种最优选择一般都采取倒序才能排除掉一些不可预知的不合法情况,我正序写了仨小时不合法情况还是没排净233.

第一份代码打表筛出了一些数量合法的情况,其实如果逆推,不可能累加到初始条件上,还是程序变得异常的慢(大概又是垫底的速度吧啊哈哈)。

期望的话,大概就是 当=+m (感谢slongle_amazing的公式),于是全部除以m即可。


#include<iostream>#include<cstring>#include<cstdlib>#include<cstdio>#include<algorithm> using namespace std; const int maxn=105;const int maxm=17; int n,m,cnt;int s[maxm];double dp[maxn][70000];int node[maxm];int shaker[1<<maxm]; int getnum(int x){    int res=0;    while(x)    {        x&=x-1;        res++;    }    return res;}int main(){    scanf("%d%d",&n,&m);    for(int i=0;i<(1<<(m+1));i++)    {        if(getnum(i)>n)continue;        shaker[++cnt]=i;    }    for(int i=1;i<=m;i++)    {        int k;        scanf("%d",s+i);        while((~scanf("%d",&k))&&k)            node[i]|=(1<<(k-1));    }    for(int i=n;i>=1;i--)        for(int j=1;j<=cnt;j++)    {        for(int k=1;k<=m;k++)        {            if((shaker[j]&node[k])==node[k])                dp[i][shaker[j]]+=max(dp[i+1][shaker[j]],dp[i+1][shaker[j]|(1<<(k-1))]+s[k])/m;            else dp[i][shaker[j]]+=dp[i+1][shaker[j]]/m;        }    }    printf("%.6lf",dp[1][0]);//终止条件 } 



#include<iostream>#include<cstring>#include<cstdlib>#include<cstdio>#include<algorithm>using namespace std;const int maxn=105;const int maxm=17;int n,m;int s[maxm];double dp[maxn][70000];int node[maxm];int main(){scanf("%d%d",&n,&m);for(int i=1;i<=m;i++){int k;scanf("%d",s+i);while((~scanf("%d",&k))&&k)node[i]|=(1<<(k-1));}for(int i=n;i>=1;i--)for(int j=0;j<(1<<m);j++){for(int k=1;k<=m;k++){if((j&node[k])==node[k])dp[i][j]+=max(dp[i+1][j],dp[i+1][j|(1<<(k-1))]+s[k])/m;else dp[i][j]+=dp[i+1][j]/m;}}printf("%.6lf",dp[1][0]);//终止条件 }