加载中…

返回上一页

状态压缩dp

所谓状态压缩,就是利用二进制位运算快的特点,用 0/1 表示是否已选,进行动态规划的一种算法.

一般能够应用状压 dp 的题目数据范围一般较小,一般在 20~40 之间.

基本操作:

1<<i-1:找到第i位并将其状态更新为 1
S&(1<<i-1):找到状态 S 中第i位状态是否为 1
S^(1<<i-1):找到状态 S 中第i位状态并将其取反.

例题:特殊方格棋盘

在n*n(n≤20)的方格棋盘上放置n 个车,某些格子不能放,求使它们不能互相攻击的方案总数.

一行一行来. 把每一行的是否放置作为状态,已经放表示为 1,没有则为 0. 使用 20 个数字,每个数字代表一行的状态.

dp[S] 为到达状态 S 所需的方案数.

由于我们发现,棋子是一行一行去放置的. 所以一个状态必然会由它的子状态贡献而来.

lowbit(x) 是将 x 中的最后一位 1 获得到. 其计算式为 x&-x,其实很好证明,拿计算器看一下二进制你就知道了.

那么就挨个去掉 1,然后再补回来呗.

那么代码很好写啦.

#define lowbit(x) (x&-x)
#define maxn 20
ll dp[1<<maxn];
int main()
{
	n=read(); dp[0]=1;
	for(rll S=1;S<1<<n;S++)
		for(rll T=i;~T;T--)
			dp[S]+=dp[S&~lowbit(T)];
	write(dp[(1<<n)-1]);
}
posted @ 2022-10-10 21:27  1Liu  阅读(13)  评论(0)    收藏  举报