要求满足任何相邻两行之间都有至少一个 骨牌横跨,任何相邻两列之间也都至少有一个骨牌横跨。
枚举有哪些列之间是没有骨牌横跨的,算出该情况下合法的方案数,容斥。
确定了哪些列是没有骨牌横跨的,列就被划分成了几个区间。
计算前\(i\)个区间的 任意两行之间有骨牌的 方案。
对于当前的\(i\),合法的方案为 任意摆放的方案,再依次减去:对于行 \([1,i-1]\) ,该行以及之前的行 任意两行之间有骨牌,该行之后的行 随意摆放的方案数。(余下的都是合法的方案)
实际上,这里需要知道某一个二维区间任意摆放的方案数(因为有不能摆放的位置),需要预处理。
这里,处理出 \([lk,rk]\)行 任意摆的方案数复杂度\(o(n^3)\),而 计算总的方案复杂度\(o(n^2)\)。
该部分的复杂度为\(o(2^n*n^3)\),当然,复杂度不满。
现在求左上端点\([l,r]\),右下端点\([l1,r1]\)的区间任意摆放的方案。
考虑枚举\(r,r1,l\),求出\(l1 \in [l,n]\)的答案。
之后就是一个轮廓线dp了,转移的时候枚举当前点的覆盖情形即可,一次的复杂度为\(o(2^n*n^2 )\)。
复杂度\(o(2^n*n^5)\)...但实际上\(n=15,m=15\)的情况下只有大约有2e8的计算。
在最终测试的时候表现十分的优秀。
#include#define rep(q,a,b) for(int q=a,q##_end_=b;q<=q##_end_;++q)#define dep(q,a,b) for(int q=a,q##_end_=b;q>=q##_end_;--q)#define mem(a,b) memset(a,b,sizeof a )#define debug(a) cerr<<#a<<' '< <<"___"<