(Lineup the Dominoes筛子)三维状压
描述:\(一堆筛子,每个筛子两个面,上面有1-6之间的数字。后一个筛子与前一个筛子的接触面的点数必须相等。\)
\(求,有多少种方案堆完筛子。(方案只关心筛子的位置,不关心是否翻转)\)
\(dp[mask][last][orientation]\),表示使用\(mask\)指示的子数组,以第\(last\)个多米诺骨牌为结尾的合法排列的方法
\(orientation\)多米诺骨牌的状态,0表示原来的方向,1表示翻转。
如果\(mask\)使用二进制表示为01010101,表示使用第0,2,4,6个多米诺骨牌排列而成,1代表使用这个位置上的数组,0代表不使用。
那么,我们先枚举所有状态,再从状态中枚举两个被用过的筛子\(last\)和\(i\)
假设last是结尾用的筛子,那么尝试接到筛子\(i\)上去
如果i和last都是原来的方向:
\(dp[mask][last][0] =sum (dp[mask][last][0],dp[premask][i][0])。\)
如果i是翻转的,last是原来的方向:
\(dp[mask][last][0] =sum (dp[mask][last][0],dp[premask][i][1])。\)
如果i是原来的方向,last是翻转的方向:
\(dp[mask][last][1] =sum (dp[mask][last][1],dp[premask][i][0])。\)
如果i和last都是翻转的方向:
\(dp[mask][last][1] =sum (dp[mask][last][1],dp[premask][i][1])。\)
最后只要将所有\(dp[1<<n-1][i][0]\)和\(dp[1<<n-1][i][1]\)累加所得即可(当\(s[i]==t[i]\)时不用加\(dp[1<<n-1][i][1]\))。
特殊情况——如果所有的多米诺骨牌都是一样的,那么所有的顺序都是有效的,即全排列。
标程
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
int s[20],t[20];
ll p[25];
ll dp[70000][20][2];
int main()
{
int T,i,mask,last,n;
p[0]=1;
for(i=1;i<=20;i++)p[i]=p[i-1]*i%mod;
scanf("%d",&T);
while(T--)
{
int fl=0;
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%d%d",&s[i],&t[i]);
for(i=1;i<n;i++)
if((s[i]==s[0]&&t[i]==t[0])||(s[i]==t[0]&&t[i]==s[0])){}
else {fl=1;break;}
// 特殊情况——如果所有的多米诺骨牌都是一样的,那么所有的顺序都是有效的。
if(fl==0)
{
printf("%lld\n",p[n]);
continue;
}
memset(dp,0,sizeof dp);
//初始化,表示每个骨牌都有一个初始状态
for(i=0;i<n;i++)
dp[1<<i][i][0]=dp[1<<i][i][1]=1;
for(mask=3;mask<(1<<n);mask++)
{
for(last=0;last<n;last++)
{
if((mask&(1<<last))==0)continue;
int premask=mask-(1<<last);
for(i=0;i<n;i++)
{
if((premask&(1<<i))==0)continue;
//i和last都是原来的方向
if(t[i]==s[last])
dp[mask][last][0] = (dp[mask][last][0]+dp[premask][i][0])%mod;
//i是翻转的,last是原来的方向
else if(s[i]==s[last])
dp[mask][last][0] = (dp[mask][last][0]+dp[premask][i][1])%mod;
//i是原来的方向,last是翻转的方向
if(t[i]==t[last])
dp[mask][last][1] = (dp[mask][last][1]+dp[premask][i][0])%mod;
//i和last都是翻转的方向
else if(s[i]==t[last])
dp[mask][last][1] = (dp[mask][last][1]+dp[premask][i][1])%mod;
}
}
}
//计算所有可能的情况
ll ans=0;
for(i=0;i<n;i++)
{
ans=(ans+dp[(1<<n)-1][i][0])%mod;
if(s[i]!=t[i])//特殊情况不再统计
ans=(ans+dp[(1<<n)-1][i][1])%mod;
}
printf("%lld\n",ans);
}
}
(Lineup the Dominoes筛子)三维状压的更多相关文章
- Long Dominoes(ZOJ 2563状压dp)
题意:n*m方格用1*3的方格填充(不能重叠)求有多少种填充方法 分析:先想状态,但想来想去就是觉得不能覆盖所有情况,隔了一天,看看题解,原来要用三进制 0 表示横着放或竖放的最后一行,1表示竖放的中 ...
- codevs1358棋盘游戏(状压dp)
1358 棋盘游戏 时间限制: 1 s 空间限制: 64000 KB 题目等级 : 大师 Master 题目描述 Description 这个游戏在一个有10*10个格子的棋盘上进行,初 ...
- 棋盘 || 状压DP
题意:有一个n*m的棋盘(n,m≤80,n*m≤80)要在棋盘上放k(k≤20)个棋子,使得任意两个棋子不相邻(每个棋子最多和周围4个棋子相邻).求合法的方案总数. 思路:对于每一行,如果把没有棋子的 ...
- UOJ #129 / BZOJ 4197 / 洛谷 P2150 - [NOI2015]寿司晚宴 (状压dp+数论+容斥)
题面传送门 题意: 你有一个集合 \(S={2,3,\dots,n}\) 你要选择两个集合 \(A\) 和 \(B\),满足: \(A \subseteq S\),\(B \subseteq S\), ...
- codeforces 342D Xenia and Dominoes(状压dp+容斥)
转载请注明出处: http://www.cnblogs.com/fraud/ ——by fraud D. Xenia and Dominoes Xenia likes puzzles ...
- HDU5731 Solid Dominoes Tilings 状压dp+状压容斥
题意:给定n,m的矩阵,就是求稳定的骨牌完美覆盖,也就是相邻的两行或者两列都至少有一个骨牌 分析:第一步: 如果是单单求骨牌完美覆盖,请先去学基础的插头dp(其实也是基础的状压dp)骨牌覆盖 hiho ...
- 【HDU 4771 Stealing Harry Potter's Precious】BFS+状压
2013杭州区域赛现场赛二水... 类似“胜利大逃亡”的搜索问题,有若干个宝藏分布在不同位置,问从起点遍历过所有k个宝藏的最短时间. 思路就是,从起点出发,搜索到最近的一个宝藏,然后以这个位置为起点, ...
- 状压dp入门
状压dp的含义 在我们解决动态规划题目的时候,dp数组最重要的一维就是保存状态信息,但是有些题目它的具有dp的特性,并且状态较多,如果直接保存的可能需要三维甚至多维数组,这样在题目允许的内存下势必是开 ...
- 状态压缩动态规划 状压DP
总述 状态压缩动态规划,就是我们俗称的状压DP,是利用计算机二进制的性质来描述状态的一种DP方式 很多棋盘问题都运用到了状压,同时,状压也很经常和BFS及DP连用,例题里会给出介绍 有了状态,DP就比 ...
随机推荐
- Linux Mint(Ubuntu)如何管理开机自动启动项?
Linux Mint自带了一个简洁的开机自启管理应用,使用方法也很简单: 依次点击“Menu”==>“控制中心”==>“个人”==>“启动应用程序”,界面如图所示: 上面打勾的就是系 ...
- Springboot启动流程简单分析
springboot启动的类为SpringApplication,执行构造函数初始化属性值后进入run方法: 然后返回ConfigurableApplicationContext(spring应用). ...
- async,await执行流看不懂?看完这篇以后再也不会了
昨天有朋友在公众号发消息说看不懂await,async执行流,其实看不懂太正常了,因为你没经过社会的毒打,没吃过牢饭就不知道自由有多重要,没生过病就不知道健康有多重要,没用过ContinueWith就 ...
- Mybatis源码详解系列(三)--从Mapper接口开始看Mybatis的执行逻辑
简介 Mybatis 是一个持久层框架,它对 JDBC 进行了高级封装,使我们的代码中不会出现任何的 JDBC 代码,另外,它还通过 xml 或注解的方式将 sql 从 DAO/Repository ...
- 关于vue切换用户,路由表不更新问题
简介 我想很多同学在项目中可能会遇到类似的问题,然后一顿操作,发现结果不尽人意.于是查阅各种资料,走进很多坑(可能你阅读的这篇随笔也是个坑).接下来我所描述的是关于我使用不同权限的用户切换登陆后,需要 ...
- C++创建动态库
[C++]创建动态库 有很多方法,这个只是其中一种 比较简洁的方法. char* __stdcall correction(char* str) char *_result = new char[se ...
- 挑战全网最幽默的Vuex系列教程:第三讲 Vuex旗下的Mutation
写在前面 上一讲「Vuex 旗下的 State 和 Getter」,告诉了我们怎么去使用仓库 store 中的状态数据.当然,光会用肯定还不够,大部分的应用场景还得对这些状态进行操控,那么具体如何操控 ...
- JavaScript之预编译
javascript是一种解释性弱类型语言,在浏览器中执行时,浏览器会先预览某段代码进行语法分析,检查语法的正确与否,然后再进行预编译,到最后才会从上往下一句一句开始执行这段代码,简单得来说可以表示为 ...
- 一行配置美化 nginx 目录 autoindex.html
demo
- Spiking-YOLO : 前沿性研究,脉冲神经网络在目标检测的首次尝试 | AAAI 2020
论文提出Spiking-YOLO,是脉冲神经网络在目标检测领域的首次成功尝试,实现了与卷积神经网络相当的性能,而能源消耗极低.论文内容新颖,比较前沿,推荐给大家阅读 来源:晓飞的算法工程笔记 公众 ...