P1896 互不侵犯(状压dp入门题)

typedef long long ll;
ll dp[10][1 << 10][100];//dp[row][sta][cnt]
int n, k, cnt;
int num[1 << 10];//存状态中1的数量
int tot[1 << 10];//存所有的可行状态

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

int main() {
	scanf("%d %d", &n, &k);
	int up = n * n;
	int limit = (1 << n);

	for (int i = 1; i < limit; ++i) {//预处理出每种状态有几个1
		num[i] = num[i - lowbit(i)] + 1;
	}
	
	for (int i = 0; i < limit; ++i) {
		if( ((i & (i >> 1)) == 0) )	tot[cnt ++] = i;
	}

	for (int i = 0; i < n; ++i) {
		for (int j = 0; j < cnt; ++j) {
			if (i == 0)	dp[i][tot[j]][num[tot[j]]] ++;
			else {
				for (int k = 0; k < cnt; ++k) {
					if ( (tot[j] & tot[k]) || ((tot[k] >> 1) & tot[j]) || ((tot[k] << 1) & tot[j]) )	continue;
					for (int z = 0; num[tot[j]] + z <= up; ++z) {
						dp[i][tot[j]][num[tot[j]] + z] += dp[i - 1][tot[k]][z];//状态转移
					}
				}
			}
		}
	}

	ll ans = 0;
	for (int i = 0; i < cnt; ++i) {
		ans += dp[n - 1][tot[i]][k];
	}
	printf("%lld\n", ans);
}


posted @ 2020-10-01 09:24  wansheking  阅读(111)  评论(0)    收藏  举报