$POJ2411\ Mondriaan's\ Dream$ 状压+轮廓线$dp$
Sol
首先状压大概是很容易想到的
一般的做法大概就是枚举每种状态然后判断转移
但是这里其实可以轮廓线dp
也就是从上到下,从左到右地放方块
假设我们现在已经放到了$(i,j)$这个位置
那么影响这个位置怎么填的其实就只有这个位置上面的位置到它左边的位置这一段的状态
于是把这一段从上到下从左往右状压起来,1表示被覆盖了,0表示没被覆盖
$f[i][j][s]$表示填到第$(i,j)$,$(i-1,j)$到$(i,j-1)$的状态为s 的方案数
转移:
原则是要把现在考虑的一行的上一行填满,不然它就永远不会被覆盖了
若$(i-1,j)=0$,即上面的格子没放,这时只能放竖起来的方块
若$(i-1,j)=1,(i,j-1)=0$即上面的格子放了,左边的格子没放,这时可以放横着的方块
若$(i-1,j)=1$即上面的格子放了,这时可以不放方块
最后要注意第一行的状态
Code
#include<iostream>
#include<cstdio>
#include<cstring>
#define Ri register int
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
int n,m;
ll f[][<<];
int main()
{
while()
{
scanf("%d%d",&n,&m);
if(!n||!m)break;
mem(f,);f[][(<<m)-]=;
for(Ri i=;i<=n;i++)
for(Ri j=,t=m*(i-)+j;j<=m;j++,t++)
for(Ri k=;k<(<<m);k++)
if(f[t-][k])
{
ll hhh=f[t-][k];
if(i> && !(k&))
f[t][(k>>)|(<<(m-))]+=hhh;
if(j> && !(k&(<<(m-))) && (k&))
f[t][(k>>)|(<<(m-))|(<<(m-))]+=hhh;
if(i==||k&)
f[t][k>>]+=hhh;
}
printf("%lld\n",f[n*m][(<<m)-]);
}
return ;
}
随机推荐
- Android内核剖析读书笔记(1)—Framework概述
一.Framework组成 1.服务端组成 a.WindowManagerService 决定各窗口的叠放次序.隐藏或者显示窗口 b.ActivityManagerService 管理应用 ...
- oracle函数 dbtimezone
[功能]:返回时区 [参数]:没有参数,没有括号 [返回]:字符型 [示例]select dbtimezone from dual;
- uda 1.C++ 函数
函数:Python vs C++ 在 Python 和 C++ 中,函数的作用相同:函数把语句组合在一起,执行某种任务.函数可以帮助你避免重复地复制和粘贴相同的代码. 函数编写的语法有些不同,主要有三 ...
- @codeforces - 1096G@ Lucky Tickets
目录 @description@ @solution@ @accepted code@ @details@ @description@ 已知一个数(允许前导零)有 n 位(n 为偶数),并知道组成这个 ...
- name和code的相关设置
cdm中同时显示name和code tools->或右键Displace preferences->Entity->Advanced->Attributes->右侧Lis ...
- @codeforces - 708D@ Incorrect Flow
目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定一个有源点与汇点的图 G,并对于每一条边 (u, v) 给定 ...
- H3C 单播与广播
- H3C 数据链路层
- Python--day19--random模块
random模块 >>> import random #随机小数 >>> random.random() # 大于0且小于1之间的小数 0.766433866365 ...
- lua在C/C++中使用table生成对应键及值
int nTop = lua_gettop(L); // 栈内初始数,假设当前为0 lua_newtable(L); // push table lua_pushstring(L,"Line ...