状态压缩。计算概率时需要注意每次概率应该除以所有可能中选中当前组合的概率。
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <cmath>
using namespace std;
#define LL long long
#define INF 1000000007
#define N 18
int n;
double a[20][20];
double dp[1 << N];
double cn(int x){
double ans = 0;
while(x > 0){
if(x & 1)ans++;
x >>= 1;
}
return n - ans;
}
int main(){
scanf("%d", &n);
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++)
scanf("%lf", &a[i][j]);
}
for(int i = 0; i < (1 << n); i++)dp[i] = 0;
dp[0] = 1;
for(int i = 0; i < (1 << n); i++){
double num = cn(i);
for(int j = 0; j < n; j++){
if(i & (1 << j))continue;
for(int k = j + 1; k < n; k++){
if(i & (1 << k))continue;
dp[i | (1 << j)] += 2 * dp[i] * a[k][j] / (num - 1) / num ;//除以num * (num - 1) / 2;
dp[i | (1 << k)] += 2 * dp[i] * a[j][k] / (num - 1) / num ;
}
}
}
for(int j = 0; j < n; j++){
printf("%f ", dp[((1 << n) - 1) ^ (1 << j)]);
}
return 0;
}