GodFly的寻宝之旅·状压DP

题意描述略,有点繁琐,点此GodFly的寻宝之旅

题解:由于只有18位,用状压DP。

首先读入边,r[i][j]表示i,j之间连边数量。

定义状态:f[i][s][w]表示停留在i点,路径集合为s,花费为w时方案总数,则答案即为sigma(f[n][s][q]),其中s为任意状态。

初始化:f[1][1][0]=1;

状态转移方程:设从i点,状态为s转移到t点,则有

f[t][s|(1<<t-1)][(0+t×num[s])%2]+=f[i][s][0]×r[i][t]

f[t][s|(1<<t-1)][(1+t×num[s])%2]+=f[i][s][1]×r[i][t]

即 下一状态方案数 +=当前方案数×转移的路径条数

很重要的一点:要先枚举状态s,在每个状态中枚举i和t。

为什么?因为如果在i或t中枚举s,则会出现「用一个还没有更新的状态去更新另一个状态」的情况。此时的答案是错误的。

最后ans=sigma(f[n][s][q]),q为询问状态。

题解结束

正文开始

位运算/状压DP常用技巧:

每位只有0,1两种状态,共有n位,枚举所有状态:

for(int s(0);s<=(1<<n)-1;s++)

第i位为1的二进制表示:

(1<<i-1)

判断状态s第i位是否为1(判断是否已经选过)

return (1<<i-1)&s

若为1,则在(i和s都为1)

若为0,不在。

将s的第i位设置为1

s=s|(1<<t-1)

| 表示按位或

猜你喜欢

转载自www.cnblogs.com/soul-M/p/9564394.html