1 条题解
-
0
自动搬运
来自洛谷,原作者为

Owen_codeisking
前OIer/ACMer/柚子厨/酒姬民搬运于
2025-08-24 21:31:24,当前版本为作者最后更新于2018-07-18 13:44:56,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
前排警告
这是写给刚学的我看的,大佬请自动忽略
人生第一道状压
互不侵犯是学术交流过的本蒟蒻今天在机房听到状压,感觉很高大上……其实就是位运算高大上一点
解释一下位运算:
& 给个例子
,返回值为
将左移位,相当于给乘上
将右移位,相当于给除以后向下取整
解释一下状压:
它的基本思想就是用二进制来优美地暴力枚举出现的方案,
若二进制下第位有赋值,则一行的第列有放牛
那么表示在前行中(包括)在个状态下的最大方案数
易得(,是第行的状态,是第行的状态)
所以我们还要再预处理一下,表示第个状态是否存在,判断条件是
&&
目标状态:全部相加
#include <bits/stdc++.h> #define ll long long using namespace std; const int p=100000000; ll f[13][1<<12],n,m; ll g[1<<12],h[1<<12],a[13][13]; ll F[13]; int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&a[i][j]); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) F[i]=(F[i]<<1)+a[i][j]; for(int i=0;i<(1<<m);i++){ if(!(i&(i>>1))&&!(i&(i<<1))){ g[i]=1; if((i&F[1])==i) f[1][i]=1; } } for(int x=2;x<=n;x++) for(int j=0;j<(1<<m);j++) if(((j&F[x-1])==j)&&g[j]) for(int k=0;k<(1<<m);k++) if(((k&F[x])==k)&&!(j&k)&&g[k]){ f[x][k]=(f[x][k]+f[x-1][j])%p; } int ans=0; for(int i=0;i<(1<<m);i++) ans=(ans+f[n][i])%p; printf("%d\n",ans); return 0; }
- 1
信息
- ID
- 848
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者