标签:并且 ogr css string qml psd bmc ash acl
https://vjudge.net/problem/UVA-11270
用$1\times2$骨牌覆盖$n\times m$棋盘,有多少种方法?
$n\times m<101$
棋盘已经填了的部分只能用考虑轮廓线表示清楚,不能只用行和列。轮廓线总共有$2^{宽}$种状态,因此需要把宽度尽量缩小。
令$n\leqslant m$,可以得到$n\leqslant 10$,所以轮廓线的状态有$2^{10}$种。
只在轮廓线的右下角放骨牌,并且保证轮廓线的上面是完全填满了的。比如下图这样的情况
每次轮廓线都会往右前进一格,那么就需要保证轮廓线第一位在前进后变成1
规定只允许对轮廓线进行修改,那么就有三种情况
其中不放和往左放都要求第一位是1,往左放还要求最后一位是0且当前位置不是第一列。
往上放要求第一位是0
轮廓线的位置有$m\times n$种,状态有$2^{n}$种,其中位置可以滚动优化掉。
初始状态是$dp[0][(1<<n)-1]=1$,而dp[0]的其他状态因为都含0,导致在后面的某个时刻无法继续转移(第一排,不能往上放,也不能往左或不放),所以虽然会被用到,最后一定会被抛弃。
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> #include<cctype> #include<cassert> #define REP(i,a,b) for(register int i=(a); i<(b); i++) #define REPE(i,a,b) for(register int i=(a); i<=(b); i++) using namespace std; typedef long long ll; int n,m; int msk, hi; ll dp[2][1<<10]; int main() { while(~scanf("%d%d", &n, &m)) { if(n>m) swap(n,m); msk = (1<<n)-1, hi=1<<(n-1); dp[0][msk]=1; int now = 0; REP(i,0,m) REP(j,0,n) { now^=1; memset(dp[now],0,sizeof(dp[now])); REPE(k,0,msk) { if(k&1) dp[now][k>>1]+=dp[now^1][k]; if(i && !(k&1)) dp[now][(k>>1)|hi]+=dp[now^1][k]; if(j && (k&1) && !(k&hi)) dp[now][((k|hi)>>1)|hi]+=dp[now^1][k]; } } printf("%lld\n", dp[now][msk]); } }
标签:并且 ogr css string qml psd bmc ash acl
原文地址:https://www.cnblogs.com/sahdsg/p/12294908.html