铺地板状压DP求方案数

2023-12-26 09:59
文章标签 dp 状压 方案 铺地板

本文主要是介绍铺地板状压DP求方案数,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

原文链接:http://blog.csdn.net/my_sunshine26/article/details/74612684


这道题搞了很久终于搞懂了,感觉受益匪浅,先贴上题目:

题目一:UESTC 1690 这是一道比CCCC简单题难的简单题


这是一道比CCCC简单题难的简单题

Time Limit: 3000/1000MS (Java/Others)     Memory Limit:65535/262140KB (Java/Others)

集训队的CFT大爷精通Python

有一天,CFT大爷跑在vps上的python爬虫程序挂了

CFT大爷经过缜密的推断,发现程序挂了的原因是Python的垃圾回收机制不够优越,导致内存炸了,那些卖vps的奸商强行杀掉了他的爬虫程序

CFT大爷决定再也不用python这门垃圾语言,他要发明一个新的语言CFTthon

CFT大爷的CFTthon是跑在CFT大爷以前写的CFT_OS上的,在CFT_OS中,内存布局是一个n*m的长方形矩阵,而CFTthon所有的变量,都只占用1*2大小的小长方形内存空间。

CFT大爷在手写CFTthonGC系统时,想到了一个问题:给定n,m,要求用CFTthon的变量把整个内存空间完全覆盖,不重合不遗漏,有多少种方法呢?

**** 扯淡题意分割线 ****

给定一个n*m的矩阵,使用1*2的小长方形覆盖矩阵,要求完全覆盖的同时不出现重合,也不允许超出边界,问有多少种可能的覆盖方法,方案数对1e9+7取模

2<=n<=1000

3<=m<=5

Input

整数n,m

Output

方案数

Sample input and output


Sample Input

Sample Output

2 4
5

 


题目二:HiHoCoder #1048 : 状态压缩·二


时间限制: 10000ms
单点时限: 1000ms
内存限制: 256MB
描述

历经千辛万苦,小Hi和小Ho终于到达了举办美食节的城市!虽然人山人海,但小Hi和小Ho仍然抑制不住兴奋之情,他们放下行李便投入到了美食节的活动当中。美食节的各个摊位上各自有着非常多的有意思的小游戏,其中一个便是这样子的:

小Hi和小Ho领到了一个大小为N*M的长方形盘子,他们可以用这个盒子来装一些大小为2*1的蛋糕。但是根据要求,他们一定要将这个盘子装的满满的,一点缝隙也不能留下来,才能够将这些蛋糕带走。

这么简单的问题自然难不倒小Hi和小Ho,于是他们很快的就拿着蛋糕离开了~

但小Ho却不只满足于此,于是他提出了一个问题——他们有多少种方案来装满这个N*M的盘子呢?

值得注意的是,这个长方形盘子的上下左右是有区别的,如在N=4, M=3的时候,下面的两种方案被视为不同的两种方案哦!

提示:我们来玩拼图吧!不过不同的枚举方式会导致不同的结果哦!

输入

每个测试点(输入文件)有且仅有一组测试数据。

每组测试数据的第一行为两个正整数N、M,表示小Hi和小Ho拿到的盘子的大小。

对于100%的数据,满足2<=N<=1000, 3<=m<=5。

输出

考虑到总的方案数可能非常大,只需要输出方案数除以1000000007的余数。


样例输入
2 4
样例输出
5

分析:

其实这两道题本质是完全一样的,就是用1*2的小长方形完全覆盖n * m的矩形有多少方案。


下面分析如何用状态压缩DP来解这道题(如果不理解为什么要用DP,为什么要用状压DP见hihoCoder题目中的提示链接,虽然我也看得云里雾里)


DP顾名思义,我们需要用到状态转移,假设我们现在正在考虑(i,j)这个位置该怎么放(此时这个位置之前的位置已经铺好了)。有三种情况:

  1. 不需要铺砖,因为在位置(i-1,j)铺的是竖砖,(i,j)已经被铺好了。(为什么不用考虑(i,j-1)铺横砖在下面会解释)
  2. 铺横砖,那么(i,j+1)也就被同时铺好了,直接考虑(i,j+2),这正解释了(1)中为什么不用考虑(i,j-1)铺横砖的情况。
  3. 铺竖砖,那么(i+1,j)也就被同时铺好了.


鉴于以上几种情况,我们将每一个位置的状态用0或1来表示,如果我们在(i,j)铺横砖,那么(i,j)和(i,j+1)都为1,如果我们在(i,j)铺竖砖,那么(i,j)为0,(i,j+1)为1。

可以用下面的图片增进理解:

那为什么要这样定义呢,我们可以这么认为,某一个位置的状态为1则表示它对下一行的状态没有限制,而为0时,表示它对下一行的状态有限制(必须为1)。(读者可以将上面的两种情况自己模拟一下)


然后下一步我们要做的就是对每个位置的放置方法进行检测可行性,并对它计数。


我们先用一个数来表示某一行的状态,这个数转化为二进制数后,第i个数*(0/1)代表该行第i列的状态。我们需要做的便是判断相邻行的状态是否合法。


判断方法的解析见代码中的注释。


由于第一行没有前驱,我们先对第一行进行特判,然后再从第二行开始进行状态转移。


用dp[i][j]表示铺到第i行,且第i行的状态为j时的总方案数。容易写出状态转移方程为dp[i][j]=dp[i][j]+dp[i-1][k](dp[i][j]一定等于i-1行能与j状态兼容的所有方案数和)

由于最后一行的状态不可能出现0,所以结果就是dp[n-1][total-1],

(计算过程中注意取模)

#include<bits/stdc++.h> 
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
const int maxn = 1000;
ll dp[maxn][1<<5];
bool one(int state,int len)    //检测某一行内部的状态是否满足要求
{
int pos=0;
while(pos<len)
{
if((state&(1<<pos))==0)  //如果这一位为0,说明这一格是竖铺的,检测下一位置
pos++;
//其余情况都是横铺的,即当前pos和pos+1的状态都为1
//当当前pos已经是最右边的或者pos+1的状态不为1
else if(pos==len-1||!(state&(1<<(pos+1))))
return false;
//满足条件就跳过对pos+1的检测
else pos+=2;
}
return true;
}
bool two(int state_pre,int state_now,int len)  //检测相邻行的状态是否满足要求
{
int pos=0;
while(pos<len)
{
if((state_pre&(1<<pos))==0)   //前一行为0,说明是竖铺,这一行的对应位置必须为1
{
if((state_now&(1<<pos))==0)
return false;
pos++;
continue;
}
if((state_now&(1<<pos))==0)  //同上
pos++;
//当前位置为1,则下一位置必须为1,且下一位置对应的前一行必须为0(竖放)
else if(pos==len-1||!((state_pre&(1<<(pos+1)))&&(state_now&(1<<(pos+1)))))
return false;
else pos+=2;
}
return true;
}
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m))
{
if(m>n)          //优化,因为此题时间、空间主要消耗在每一行的多种状态上
swap(m,n);
int total=1<<m;  //一行的所有状态数
memset(dp,0,sizeof(dp));
for(int i=0;i<total;i++)
{
if(one(i,m))
{
dp[0][i]=1;//表示在第0行 状态为i的时候满足条件置为1 
}
}
for(int i=1;i<n;i++)
for(int j=0;j<total;j++)     //当前一行的状态
for(int k=0;k<total;k++)     //前一行的状态
{
if(two(j,k,m))
{
dp[i][j]=(dp[i][j]+dp[i-1][k])%mod;//当前方案数+上上一行满足条件的时候的方案 
}
}
printf("%lld\n",dp[n-1][total-1]);
}
return 0;
}



这篇关于铺地板状压DP求方案数的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/538993

相关文章

无人叉车3d激光slam多房间建图定位异常处理方案-墙体画线地图切分方案

墙体画线地图切分方案 针对问题:墙体两侧特征混淆误匹配,导致建图和定位偏差,表现为过门跳变、外月台走歪等 ·解决思路:预期的根治方案IGICP需要较长时间完成上线,先使用切分地图的工程化方案,即墙体两侧切分为不同地图,在某一侧只使用该侧地图进行定位 方案思路 切分原理:切分地图基于关键帧位置,而非点云。 理论基础:光照是直线的,一帧点云必定只能照射到墙的一侧,无法同时照到两侧实践考虑:关

高效+灵活,万博智云全球发布AWS无代理跨云容灾方案!

摘要 近日,万博智云推出了基于AWS的无代理跨云容灾解决方案,并与拉丁美洲,中东,亚洲的合作伙伴面向全球开展了联合发布。这一方案以AWS应用环境为基础,将HyperBDR平台的高效、灵活和成本效益优势与无代理功能相结合,为全球企业带来实现了更便捷、经济的数据保护。 一、全球联合发布 9月2日,万博智云CEO Michael Wong在线上平台发布AWS无代理跨云容灾解决方案的阐述视频,介绍了

hdu4826(三维DP)

这是一个百度之星的资格赛第四题 题目链接:http://acm.hdu.edu.cn/contests/contest_showproblem.php?pid=1004&cid=500 题意:从左上角的点到右上角的点,每个点只能走一遍,走的方向有三个:向上,向下,向右,求最大值。 咋一看像搜索题,先暴搜,TLE,然后剪枝,还是TLE.然后我就改方法,用DP来做,这题和普通dp相比,多个个向上

hdu1011(背包树形DP)

没有完全理解这题, m个人,攻打一个map,map的入口是1,在攻打某个结点之前要先攻打其他一个结点 dp[i][j]表示m个人攻打以第i个结点为根节点的子树得到的最优解 状态转移dp[i][ j ] = max(dp[i][j], dp[i][k]+dp[t][j-k]),其中t是i结点的子节点 代码如下: #include<iostream>#include<algorithm

hdu4865(概率DP)

题意:已知前一天和今天的天气概率,某天的天气概率和叶子的潮湿程度的概率,n天叶子的湿度,求n天最有可能的天气情况。 思路:概率DP,dp[i][j]表示第i天天气为j的概率,状态转移如下:dp[i][j] = max(dp[i][j, dp[i-1][k]*table2[k][j]*table1[j][col] )  代码如下: #include <stdio.h>#include

usaco 1.1 Broken Necklace(DP)

直接上代码 接触的第一道dp ps.大概的思路就是 先从左往右用一个数组在每个点记下蓝或黑的个数 再从右到左算一遍 最后取出最大的即可 核心语句在于: 如果 str[i] = 'r'  ,   rl[i]=rl[i-1]+1, bl[i]=0 如果 str[i] = 'b' ,  bl[i]=bl[i-1]+1, rl[i]=0 如果 str[i] = 'w',  bl[i]=b

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

技术背景 好多开发者需要遴选Android平台RTSP直播播放器的时候,不知道如何选的好,本文针对常用的方案,做个大概的说明: 1. 使用VLC for Android VLC Media Player(VLC多媒体播放器),最初命名为VideoLAN客户端,是VideoLAN品牌产品,是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影

uva 10154 DP 叠乌龟

题意: 给你几只乌龟,每只乌龟有自身的重量和力量。 每只乌龟的力量可以承受自身体重和在其上的几只乌龟的体重和内。 问最多能叠放几只乌龟。 解析: 先将乌龟按力量从小到大排列。 然后dp的时候从前往后叠,状态转移方程: dp[i][j] = dp[i - 1][j];if (dp[i - 1][j - 1] != inf && dp[i - 1][j - 1] <= t[i]

uva 10118 dP

题意: 给4列篮子,每次从某一列开始无放回拿蜡烛放入篮子里,并且篮子最多只能放5支蜡烛,数字代表蜡烛的颜色。 当拿出当前颜色的蜡烛在篮子里存在时,猪脚可以把蜡烛带回家。 问最多拿多少只蜡烛。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cs

uva 10069 DP + 大数加法

代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <queue>#include <map>#include <cl