题目传送门https://vjudge.net/problem/CSES-2181#author=GPT_zh
解题思路
观察到 ,可以使用状压 DP ……
设 表示第
列,当前列的状态(放了方块为 1,没放为 0)。
可以记忆化搜索,这样比较好理解……
对于当前的第 列和状态
,我们应该是可以推出下一列的所有可能状态的:
若当前有两个连续需要拼的格子,我们可以放一个 的方块
若当前需要填方块但是没有连续的,那么就只能放置一个 的方块,那么就会影响下一列的方块状态,这时直接记录。
计算出下一列的可能状态之后,直接遍历累加方案即可。
主要就是这些,直接上代码……
代码
#include<bits/stdc++.h>
using namespace std;
int n,m;
int f[1001][1<<11];
const int mod=1e9+7;
void go(int msk,int i,int nxt,vector<int>& g)
{
if(i>n)
{
g.push_back(nxt);
return;
}
if(msk&(1<<i))
{
go(msk,i+1,nxt,g);
}
if(i<n)
{
if(!(msk&(1<<i))&&!(msk&(1<<(i+1))))
{
go(msk,i+2,nxt,g);
}
}
if(!(msk&(1<<i)))
{
go(msk,i+1,nxt | (1<<i),g);
}
}
int dfs(int x,int msk)
{
if(x>m)
{
if(msk==0)return 1;
return 0;
}
if(f[x][msk]!=-1)return f[x][msk];
vector<int> g;
int ans=0;
go(msk,1,0,g);
for(auto y:g)
{
(ans+=dfs(x+1,y))%=mod;
}
g.clear();
f[x][msk]=ans;
return ans;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n>>m;
memset(f,-1,sizeof f);
cout<<dfs(1,0);
return 0;
}