dp合集 广场铺砖问题&&硬木地板
dp合集 广场铺砖问题&&硬木地板
很经典了吧。。。
前排:思想来自yali朱全民dalao的ppt百度文库免费下载
后排:STO朱全民OTZ
广场铺砖问题
有一个 W 行 H 列的广场,需要用 1*2 小砖铺盖,小砖之间互相不能重叠,问
有多少种不同的铺法?
输入数据:
只有一行 2 个整数,分别为 W 和 H,( 1<=W, H<=11)
输出数据:
只有 1 个整数,为所有的铺法数。
样例:
Floor.in
2 4
Floor.out
5
dfs、bfs。。。算了吧
然而我看了一眼ppt,这不是SBT吗???
然后就写出来了
设f[i][j]表示第i行,状态为j的转移方法数
具体思想:一个状态有两种方式转移:全竖放转移and横放一个转移。
然后WA了
原因:横放可能有重复(比如□□□□,可以先左边两个也可以先右边两个),然后GG
// It is made by XZZ
#include<cstdio>
#include<algorithm>
#define lb(a) (a&-a)
#define Fname "floor"
using namespace std;
#define rep(a,b,c) for(rg int a=b;a<=c;a++)
#define drep(a,b,c) for(rg int a=b;a>=c;a--)
#define erep(a,b) for(rg int a=fir[b];a;a=nxt[a])
#define il inline
#define rg register
#define vd void
typedef long long ll;
il int gi(){
rg int x=0;rg char ch=getchar();
while(ch<'0'||ch>'9')ch=getchar();
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x;
}
int f[12][1<<11];
int cnt[1<<11],s[1<<11];
il bool cmp(int a,int b){return cnt[a]<cnt[b];}
int main(){
#ifdef xzz
freopen(Fname".in","r",stdin);
freopen(Fname".out","w",stdout);
#endif
int n=gi(),m=gi();
if((n*m)&1){puts("0");return 0;}
f[0][0]=1;
int tot=(1<<m)-1;
rep(i,0,tot){
int j=i;
while(j)++cnt[i],j-=lb(j);
}
rep(i,0,tot)s[i]=i;
sort(s+1,s+tot+1,cmp);
int g,j;
rep(i,0,n-1)rep(jj,0,tot){
j=s[jj];
g=f[i][j];
printf("f[%d][%d]=%d\n",i,j,f[i][j]);
f[i+1][(~j)&tot]+=g;//所有的都竖放
rep(k,0,m-2)if(!((1<<k)&j)&&!((1<<k+1)&j))f[i][j|(1<<k)|(1<<k+1)]+=g;
}
printf("%d\n",f[n][0]);
return 0;
}
解决办法:一次转移
即通过dfs完成转移,做到不重不漏
在一个状态下dfs下一排可能的所有状态
具体见ppt
// It is made by XZZ
#include<cstdio>
#include<algorithm>
#define lb(a) (a&-a)
#define Fname "floor"
using namespace std;
#define rep(a,b,c) for(rg int a=b;a<=c;a++)
#define drep(a,b,c) for(rg int a=b;a>=c;a--)
#define erep(a,b) for(rg int a=fir[b];a;a=nxt[a])
#define il inline
#define rg register
#define vd void
typedef long long ll;
il int gi(){
rg int x=0;rg char ch=getchar();
while(ch<'0'||ch>'9')ch=getchar();
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x;
}
ll f[12][1<<11],n,m;
il vd dfs(const ll&F,const int&i,const int&j,int x,int now){
if(now==m)f[i+1][x]+=F;
else if(j&(1<<now))dfs(F,i,j,x,now+1);//已经有了
else{
dfs(F,i,j,x|(1<<now),now+1);//竖着
if((now!=m-1)&&!(j&(1<<now+1)))dfs(F,i,j,x,now+2);//横着
}
}
int main(){
#ifdef xzz
freopen(Fname".in","r",stdin);
freopen(Fname".out","w",stdout);
#endif
n=gi(),m=gi();
if((n*m)&1){puts("0");return 0;}
f[0][0]=1;
rep(i,0,n-1)rep(j,0,(1<<m)-1)dfs(f[i][j],i,j,0,0);
printf("%lld\n",f[n][0]);
return 0;
}
其实还可以有更快的:每个j转移过去的都相同,可以先预处理每个j转移的,用邻接表实现,应该快的飞起
虽然我懒得写了(逃
硬木地板
举行计算机科学家盛宴的大厅的地板为 M×N (1<=M<=9, 1<=N<=9)的矩形。现在必须要铺上硬木地板砖。可以使用的地板砖形状有两种:
- 2×1 的矩形砖
- 2×2 中去掉一个 1×1 的角形砖
你需要计算用这些砖铺满地板共有多少种不同的方案。
注意:必须盖满,地板砖数量足够多,不能存在同时被多个板砖覆盖的部分。
输入数据
包含 M 和 N。
输出数据
输出方案总数,如果不可能那么输出 0 。
样例
输入:floor.in
2 3
输出:floor.out
5
会上面那个基本就会这个了额。。。
改一下dfs就好了
// It is made by XZZ
#include<cstdio>
#include<algorithm>
#define Fname "floor2"
using namespace std;
#define rep(a,b,c) for(rg int a=b;a<=c;a++)
#define drep(a,b,c) for(rg int a=b;a>=c;a--)
#define erep(a,b) for(rg int a=fir[b];a;a=nxt[a])
#define il inline
#define rg register
#define vd void
typedef long long ll;
il int gi(){
rg int x=0;rg char ch=getchar();
while(ch<'0'||ch>'9')ch=getchar();
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x;
}
ll f[10][1<<9],n,m;
il vd dfs(const ll&F,const int&i,const int&j,int x,int now){
if(now==m)f[i+1][x]+=F;
else if(j&(1<<now))dfs(F,i,j,x,now+1);
else{
if(!(x&(1<<now))){
dfs(F,i,j,x|(1<<now),now+1);//竖着
if(now&&(!(x&(1<<now-1))))dfs(F,i,j,x|(1<<now)|(1<<now-1),now+1);//┘
if(now!=m-1)dfs(F,i,j,x|(1<<now)|(1<<now+1),now+1);//└
}
if((now!=m-1)&&!(j&(1<<now+1))){
dfs(F,i,j,x,now+2);//横着
if(!(x&(1<<now)))dfs(F,i,j,x|(1<<now),now+2);//┌
dfs(F,i,j,x|(1<<now+1),now+2);//┐
}
}
}
int main(){
#ifdef xzz
freopen(Fname".in","r",stdin);
freopen(Fname".out","w",stdout);
#endif
n=gi(),m=gi();
f[0][0]=1;
rep(i,0,n-1)rep(j,0,(1<<m)-1)dfs(f[i][j],i,j,0,0);
printf("%lld\n",f[n][0]);
return 0;
}
PS.具体参见上面ppt链接
dp合集 广场铺砖问题&&硬木地板的更多相关文章
- 9.15 DP合集水表
9.15 DP合集水表 显然难了一些啊. 凸多边形的三角剖分 瞄了一眼题解. 和蛤蛤的烦恼一样,裸的区间dp. 设f[i][j]表示i~j的点三角剖分最小代价. 显然\(f[i][i+1]=0,f[i ...
- 9.14 DP合集水表
9.14 DP合集水表 关键子工程 在大型工程的施工前,我们把整个工程划分为若干个子工程,并把这些子工程编号为 1. 2. --. N:这样划分之后,子工程之间就会有一些依赖关系,即一些子工程必须在某 ...
- 【CJOJ2498】【DP合集】最长上升子序列 LIS
题面 Description 给出一个 1 ∼ n (n ≤ 10^5) 的排列 P 求其最长上升子序列长度 Input 第一行一个正整数n,表示序列中整数个数: 第二行是空格隔开的n个整数组成的序列 ...
- CJOJ 【DP合集】最长上升序列2 — LIS2
题面 已知一个 1 ∼ N 的排列的最长上升子序列长度为 K ,求合法的排列个数. 好题(除了我想不出来我应该找不到缺点), 想一想最长上升子序列的二分做法, 接在序列后面或者替换. 所以对于每一个位 ...
- 【DP合集】tree-knapsack
Description 给出一个 N 个节点的有根树,点编号 1 ∼ N ,编号为 i 的点有权值 v i .请选出一个包含树根的,点数 不超过 K 的连通块,使得点权和最大. Input 输入的第一 ...
- 【DP合集】m-knapsack
给出 n 个物品,第 i 个物品有重量 w i .现在有 m 个背包,第 i 个背包的限重为 c i ,求最少用几个背 包能装下所有的物品. Input 输入的第一行两个整数 n, m ( n ≤ 2 ...
- 【DP合集】背包 bound
N 种物品,第 i 种物品有 s i 个,单个重量为 w i ,单个价值为 v i .现有一个限重为 W 的背包,求能容 纳的物品的最大总价值. Input 输入第一行二个整数 N , W ( N ≤ ...
- 【DP合集】合并 union
给出一个 1 ∼ N 的序列 A ( A 1 , A 2 , ..., A N ) .你每次可以将两个相邻的元素合并,合并后的元素权值即为 这两个元素的权值之和.求将 A 变为一个非降序列,最少需要多 ...
- 【DP合集】棋盘 chess
给出一张 n × n 的棋盘,格子有黑有白.现在要在棋盘上放棋子,要求: • 黑格子上不能有棋子 • 每行每列至多只有一枚棋子 你的任务是求出有多少种合法的摆放方案.答案模 109+7109+7 . ...
随机推荐
- redis.conf 具体配置详解
redis.conf 具体配置详解 # redis 配置文件示例 # 当你需要为某个配置项指定内存大小的时候,必须要带上单位, # 通常的格式就是 1k 5gb 4m 等酱紫: # # 1k => ...
- ps基础练习
1. 直接把图片拖进来 2. F 键 视窗全屏快捷键 3. 此时的图片是“背景”层,不能直接编辑,双击该背景层,就变成了“图层”,就可以编辑了 4. 5. 6. 7. 魔棒工具,在需要去掉的点一下, ...
- C#流概述
C#流概述 .NET Framework使用“流”来支持读取或写入文件.可以将流视为一组连续的一维数据,包含开头和结尾,并且其中的游标指示了流的当前位置. 1.流操作 流中包含的数据可能来自内存.文件 ...
- rocketmq搭建
maven参数: mvn -Prelease-all -DskipTests clean install -U
- 【题解】洛谷P1273 有线电视网(树上分组背包)
次元传送门:洛谷P1273 思路 一开始想的是普通树形DP 但是好像实现不大好 观摩了一下题解 是树上分组背包 设f[i][j]为以i为根的子树中取j个客户得到的总价值 我们可以以i为根有j组 在每一 ...
- Python中获取异常(try Exception)信息
异常信息的获取对于程序的调试非常重要,可以有助于快速定位有错误程序语句的位置. 这里获取异常(Exception)信息采用try...except...程序结构.如下所示: try: ... exce ...
- HDFS的Read过程分析
在hadoop中作为后端存储的文件系统HDFS发挥中重要的作用,HDFS是一个分布式文件系统,按照Google File System的思想开发的,针对的场景是低端服务器.写操作少而读操作多的情况.在 ...
- 微服务之配置中心ConfigKeeper
在微服务架构中,配置中心是必不可少的基础服务.ConfigKeeper已开源,本文将深度分析配置中心的核心内容,错过「Spring Cloud中国社区北京沙龙-2018.10.28 」的同学将从本篇文 ...
- Angular7教程-04-Angular常用操作(下)
6. 数据双向绑定 视图和数据,只要一方发生变化,另一方跟着变化. 好处是不需要在代码中手动更新视图,简化开发,增加代码内聚性,代码可读性更强. 缺点是当绑定的数据层次深.数据量大时,会影响性能. 双 ...
- MVC和MVT的区别
首先,MVC和MVT是框架式不是设计模式. 框架与设计模式虽然相似,但却有着根本的不同.设计模式是对在某种环境中反复出现的问题以及解决该问题的方案的描述,它比框架更抽象:框架可以用代码表示,也能直接执 ...