ZOJ 3777 Problem Arrangement

状态压缩,$dp$。

要计算期望,期望等于概率的倒数,事实上也就是要计算方案数,可以利用状态压缩$dp$,$dp[s][m]$表示状态$s$下,取得$m$价值的方案数,转移即可。

#include<cstdio>
#include<queue>
#include<algorithm>
#include<vector>
#include<cstring>
using namespace std;

long long dp[4200][510];
int T,n,m,p[510][510];
int num[4200];

int main()
{
    for(int i=0;i<4096;i++)
    {
        num[i]=0;
        for(int j=0;j<12;j++)
        {
            if((1<<j)&i) num[i]++;
        }
    }

    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++) scanf("%d",&p[i][j]);

        memset(dp,0,sizeof dp);
        dp[0][0]=1;

        for(int i=0;i<(1<<n);i++)
        {
            for(int j=0;j<m;j++)
            {
                if(dp[i][j]==0) continue;
                for(int k=0;k<n;k++)
                {
                    if((1<<k)&i) continue;
                    if(j+p[k][num[i]]<m) dp[i|(1<<k)][j+p[k][num[i]]] += dp[i][j];
                }
            }
        }

        long long B=1;
        for(int i=1;i<=n;i++) B=B*i;

        long long A=0;
        for(int i=0;i<m;i++)
        {
            A=A+dp[(1<<n)-1][i];
        }

        A=B-A;

        if(A==0)
        {
            printf("No solution\n");
            continue;
        }

        long long GCD = __gcd(A,B);

        printf("%lld/%lld\n",B/GCD,A/GCD);
    }
    return 0;
}

 

posted @ 2017-03-16 21:38  Fighting_Heart  阅读(188)  评论(0编辑  收藏  举报