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; }