1. 程式人生 > 實用技巧 >CodeForces - 16E(狀壓dp)

CodeForces - 16E(狀壓dp)

const int maxn = 5e4 + 10;
double dp[1 << 18];
int num[1 << 18];
double pic[20][20];
int sta[20][maxn], cnt[20];

int lowbit(int x) {
	return (x & (-x));
}

int main() {
	int n;
	scanf("%d", &n);
	for (int i = 0; i < n; ++i)
		for (int j = 0; j < n; ++j)
			scanf("%lf", &pic[i][j]);

	int limit = (1 << n);
	
	for (int i = 1; i < limit; ++i)	num[i] = num[i - lowbit(i)] + 1;

	for (int i = 0; i < limit; ++i) {//預處理出不同種1個數的狀態
		int temp = num[i];
		sta[temp][cnt[temp] ++] = i;
	}

	dp[limit - 1] = 1;
	for (int i = n-1; i >= 1; --i) {//剩餘的魚條數
		for (int j = 0; j < cnt[i]; ++j) {
			int now = sta[i][j];//當前狀態
			for (int k = 0; k < n; ++ k) {//添個1
				int pre = (now | (1 << k));
				if (pre == now)	continue;
				int c = (i * (i + 1)) / 2;//C(i+1, 2), 即兩條魚中間偶遇的可能
				for(int z = 0; z < n; ++ z)
					if((1 << z) & pre)	dp[now] += dp[pre] * pic[z][k] / c;
			}
		}
	}

	for (int i = 1; i < limit; i <<= 1)
		printf("%.6lf%c", dp[i], i == limit - 1 ? '\n' : ' ');
	
	return 0;
}