2014 Super Training #4 B Problem Arrangement --状压DP

原题:ZOJ 3777  http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3777

题意:给每个题目安排在每个位置的value。有一个程序随机选择安排的顺序,总的value值大于等于m时,就可以接受这个安排。问能够获得一次满足条件的安排的期望次数。

这题不会做,看网上是用状态压缩DP做的。

定义: dp[i][j]为选取了前i行,趣味和为j的方案种数。

由于程序是每次随机选择一个排列,每次的选择之间不影响,而且每次选中的概率相等,都为dp[S][m]/ fac[n] , 即满足条件的总数/ 总排列数。由于01分布的期望为p , 这里p = dp[S][m]/ fac[n],p为试验一次事件发生的概率,那么,事件一定发生试验的次数为1/p 。 所以结果为  fac[n]/dp[S][m] ,结果用最简形式表示。(S = (1<<n)-1). (参考玻璃年华Alex

方程:dp[i|(1<<j)][k+a[R][j]] += dp[i][k];   

 i 即一个01串,其中1的个数表示已经选择的行数,用R表示,则下一次要选第R+1行的数(由于下标从0开始,所以仍是a[R][j]),1的位置表示选取的前i行中选取的数的列的情况,下一次选的时候就不能选这些列了。 然后转移,如果k + a[R][j] > m,则令其为m即可,因为大于m后值就没有意义了。

代码:

#include <iostream>

#include <cstdio>

#include <cstring>

#include <cmath>

#include <algorithm>

using namespace std;

#define N 14



int fac[N],a[N][N];

int dp[5007][510];



void INIT_FAC()

{

    fac[1] = 1;

    for(int i=2;i<=12;i++)

        fac[i] = fac[i-1]*i;

}



int gcd(int a,int b)

{

    if(!b)

        return a;

    return gcd(b,a%b);

}



int main()

{

    int t,n,m,i,j,k,R;

    INIT_FAC();

    scanf("%d",&t);

    while(t--)

    {

        scanf("%d%d",&n,&m);

        for(i=0;i<n;i++)

            for(j=0;j<n;j++)

                scanf("%d",&a[i][j]);

        memset(dp,0,sizeof(dp));

        dp[0][0] = 1;

        int S = (1<<n)-1;

        for(i=0;i<=S;i++)

        {

            R = 0;

            for(j=0;j<n;j++)

                if(i & (1<<j))

                    R++;

            //已访问R行

            for(j=0;j<n;j++) //放置第R+1行(下标仍为R),枚举其放置的列

            {

                if(i & (1<<j)) //这列已用过

                    continue;

                for(k=0;k<=m;k++)  //枚举和

                    dp[i|(1<<j)][min(k+a[R][j],m)] += dp[i][k];  //和超过m算作m

            }

        }

        if(dp[S][m])

        {

            int g = gcd(fac[n],dp[S][m]);

            printf("%d/%d\n",fac[n]/g,dp[S][m]/g);

        }

        else

            puts("No solution");

    }

    return 0;

}
View Code

 

你可能感兴趣的:(super)